【发布时间】:2022-12-24 04:40:33
【问题描述】:
根据this和this,将取消令牌传递给任务构造函数或Task.Run,将导致任务与所述令牌相关联,导致任务转换为Canceled而不是Faulted如果发生取消异常。
一段时间以来,我一直在摆弄这些示例,除了阻止已取消的任务启动之外,我看不到任何好处。
更改this MSDN example上的代码
tc = Task.Run(() => DoSomeWork(i, token), token);
到
tc = Task.Run(() => DoSomeWork(i, token));
产生了完全相同的输出:
此代码还会导致两个已取消的状态任务并抛出相同的异常:
var token = cts.Token;
var t1 = Task.Run(() =>
{
while (true)
{
Thread.Sleep(1000);
token.ThrowIfCancellationRequested();
};
});
var t2 = Task.Run(() =>
{
while (true)
{
Thread.Sleep(1000);
token.ThrowIfCancellationRequested();
};
}, token);
Console.ReadKey();
try
{
cts.Cancel();
Task.WaitAll(t1, t2);
}
catch(Exception e)
{
if (e is AggregateException)
{
foreach (var ex in (e as AggregateException).InnerExceptions)
{
Console.WriteLine(e.Message);
}
}
else
Console.WriteLine(e.Message);
}
Console.WriteLine($"without token: { t1.Status }");
Console.WriteLine($"with token: { t2.Status }");
Console.WriteLine("Done.");
显然,从任务中抛出 OperationCanceledException 足以使其转换为 Canceled 而不是 Faulted。所以我的问题是:除了阻止已取消的任务运行之外,是否还有其他原因将令牌传递给任务?
【问题讨论】:
-
我敢肯定,当您从取消的令牌开始时,您应该会看到不同之处。
-
它有,如果你阅读我的问题,你会注意到我链接了最相关的。
-
“阻止取消的任务开始”正是我认为的重点,我不明白为什么你需要另一个理由
-
因为与此问题相关的每个答案都指出有两个原因,另一个是阻止任务进入故障状态,但似乎不再以这种方式工作。
-
@DavidL AFAICS linked answer 没有解释为什么未通过
cancellationToken的t1最终处于Canceled状态。
标签: c# task cancellation-token