未调用cts.Cancel(),Task为何抛出TaskCanceledException异常?
为什么没调用
cts.Cancel()却抛出TaskCanceledException? 核心原因出在你用的TaskContinuationOptions.OnlyOnCanceled选项上,和CancellationTokenSource本身没关系:
- 你的主任务(
StartNew内的逻辑)抛出了普通异常,最终会进入**Faulted(故障)**状态。 - 你给主任务绑定的延续任务指定了
OnlyOnCanceled,这个选项的意思是只有当主任务被取消时,延续任务才会被执行。但现在主任务是故障状态,不满足触发条件,所以这个延续任务根本不会被调度执行,直接进入**Canceled(取消)**状态。 - 当你
await这个已取消的延续任务时,就会自动抛出TaskCanceledException——这就是报错的来源。
怎么解决?
如果你想处理主任务的异常,别用OnlyOnCanceled,换成OnlyOnFaulted;或者更推荐用async/await原生的try-catch直接捕获主任务异常,比ContinueWith更直观:
方案1:直接捕获主任务异常
var cts = new CancellationTokenSource(); try { await Task.Factory.StartNew(() => { throw new Exception("测试异常"); }, cts.Token); } catch (Exception ex) { // 在这里处理主任务抛出的异常 Console.WriteLine($"捕获到异常:{ex.Message}"); }
方案2:用ContinueWith分别处理不同状态
如果一定要用ContinueWith,可以给不同任务状态绑定对应的延续逻辑:
var cts = new CancellationTokenSource(); var mainTask = Task.Factory.StartNew(() => { throw new Exception("测试异常"); }, cts.Token); // 处理主任务故障的情况 await mainTask.ContinueWith(t => { Console.WriteLine($"主任务异常:{t.Exception.InnerException.Message}"); }, TaskContinuationOptions.OnlyOnFaulted); // 处理主任务被取消的情况(如果有需要) await mainTask.ContinueWith(t => { Console.WriteLine("主任务已取消"); }, TaskContinuationOptions.OnlyOnCanceled);
内容的提问来源于stack exchange,提问作者theateist
相关产品推荐
相关产品推荐

