Task.Run 和 CancellationToken。在这种情况下取消是如何工作的?
Task.Run and CancellationToken. How does cancellation work in this scenario?
为什么我们在接下来的 2 个场景中有 2 个不同的结果?在这些样本中
token.IsCancellationRequested = 正确。如果我评论 if(token.IsCancellationRequested),为什么功能会发生变化,而实际上我们可以键入 if(true) 而不是它。
我在某处读到,为了获得 TaskCanceledException(Status = Canceled),我们需要遵循接下来的 3 个条件:
- 抛出 OperationCanceledException 并将令牌传递给它的构造函数
- 将相同的令牌传递给创建任务的方法 (Task.Run)
- IsCancellationRequested 应该为真。
确实如此,如果我们使用 if(token.IsCancellationRequested) throw new OperationCanceledException(token) (等于 token.ThrowIfCancellationRequested)(第二种情况),我们需要遵循其他 2 个条件,但在第一种情况,如果我们评论 if(token.IsCancellationRequested)(我们甚至可以从 CTS 构造函数中删除 1),我们仍然会获得 Canceled 状态。
1.这里的状态是 Canceled
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);
似乎如果编译器能够在编译时知道任务将始终抛出 OperationCanceledException
将以 Canceled
状态结束,否则它将以 Faulted
结束。
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource(1);
cts.Cancel();
var token = cts.Token;
var task = Task.Run(() =>
{
//if(GetTrue()) //Faulted
if(true) //Canceled
throw new OperationCanceledException();
});
Thread.Sleep(50);
Console.WriteLine(task.Status);
}
bool GetTrue()
{
return true;
}
但是,如果您将相同的令牌发送到 Task.Run
,因为您将其放入任务中,它将以 Canceled
结束。
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource(10000);
var token = cts.Token;
var task = Task.Run(() =>
{
cts.Cancel();
token.ThrowIfCancellationRequested();
}, token);
Thread.Sleep(50);
Console.WriteLine(task.Status);
}
为什么我们在接下来的 2 个场景中有 2 个不同的结果?在这些样本中 token.IsCancellationRequested = 正确。如果我评论 if(token.IsCancellationRequested),为什么功能会发生变化,而实际上我们可以键入 if(true) 而不是它。
我在某处读到,为了获得 TaskCanceledException(Status = Canceled),我们需要遵循接下来的 3 个条件:
- 抛出 OperationCanceledException 并将令牌传递给它的构造函数
- 将相同的令牌传递给创建任务的方法 (Task.Run)
- IsCancellationRequested 应该为真。
确实如此,如果我们使用 if(token.IsCancellationRequested) throw new OperationCanceledException(token) (等于 token.ThrowIfCancellationRequested)(第二种情况),我们需要遵循其他 2 个条件,但在第一种情况,如果我们评论 if(token.IsCancellationRequested)(我们甚至可以从 CTS 构造函数中删除 1),我们仍然会获得 Canceled 状态。
1.这里的状态是 Canceled
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);
似乎如果编译器能够在编译时知道任务将始终抛出 OperationCanceledException
将以 Canceled
状态结束,否则它将以 Faulted
结束。
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource(1);
cts.Cancel();
var token = cts.Token;
var task = Task.Run(() =>
{
//if(GetTrue()) //Faulted
if(true) //Canceled
throw new OperationCanceledException();
});
Thread.Sleep(50);
Console.WriteLine(task.Status);
}
bool GetTrue()
{
return true;
}
但是,如果您将相同的令牌发送到 Task.Run
,因为您将其放入任务中,它将以 Canceled
结束。
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource(10000);
var token = cts.Token;
var task = Task.Run(() =>
{
cts.Cancel();
token.ThrowIfCancellationRequested();
}, token);
Thread.Sleep(50);
Console.WriteLine(task.Status);
}