【发布时间】:2021-03-09 23:29:04
【问题描述】:
为什么我们在接下来的 2 个场景中有 2 个不同的结果?在这些样本中 token.IsCancellationRequested = true。如果我评论 if(token.IsCancellationRequested),为什么功能会发生变化,而实际上我们可以输入 if(true) 而不是它。
我在某处读到,为了获得 TaskCanceledException ( Status = Canceled ),我们需要遵循以下 3 个条件:
- 抛出 OperationCanceledException 并将令牌传递给它的构造函数
- 将相同的令牌传递给创建任务 (Task.Run) 的方法
- IsCancellationRequested 应该为真。
确实如此,如果我们使用 if(token.IsCancellationRequested) throw new OperationCanceledException(token) (equals to token.ThrowIfCancellationRequested) (第二种情况),我们需要遵循其他 2 个条件,但在第一种情况下,如果我们评论 if (token.IsCancellationRequested)(我们甚至可以从 CTS 构造函数中删除 1)我们仍然会得到 Canceled 状态。
1.此处状态已取消
CancellationTokenSource cts = new CancellationTokenSource(1);
var token = cts.Token;
var task = Task.Run(() =>
{
Thread.Sleep(5);
// if(token.IsCancellationRequested)
throw new OperationCanceledException(token);
});
Thread.Sleep(50);
Console.WriteLine(task.Status);
2.这里 - 故障。
CancellationTokenSource cts = new CancellationTokenSource(1);
var token = cts.Token;
var task = Task.Run(() =>
{
Thread.Sleep(5);
if(token.IsCancellationRequested) // true
throw new OperationCanceledException(token);
});
Thread.Sleep(50);
Console.WriteLine(task.Status);
【问题讨论】:
-
顺便说一句 - 你应该打电话给
ThrowIfCancellationRequested,而不是测试/扔自己 -
if(token.IsCancellationRequested) throw new OperationCanceledException(token) 等于 ThrowIfCancellationRequested,但在某处我读到,为了拥有 TaskCanceledException (Status = Canceled),我们需要: 1. 抛出 OperationCanceledException 并通过将令牌传递给它的构造函数 2. 将相同的令牌传递给创建任务 (Task.Run) 的方法 3. IsCancellationRequested 应该为 true
-
我认为
TaskCanceledException只是捕获OperationCanceledException的结果。但这样做的规范方法是使用ThrowIfCancellationRequested(),这取决于IsCancellationRequested -
您的两个示例调用了
Task.Run()的不同重载,这反过来又具有不同的取消行为。查看副本。
标签: c# .net task-parallel-library