好的,所以我了解如何使用CancellationTokenSource
取消任务。在我看来,Task
类型"类型"自动处理此异常 - 它将Task
' s Status
设置为已取消。
现在你仍然需要处理OperationCancelledException
。否则异常会冒泡到Application.UnhandledException
。 Task本身识别它并在内部进行一些处理,但是你仍然需要将调用代码包装在try块中以避免未处理的异常。有时,这似乎是不必要的代码。如果用户按下取消,则取消Task
(显然任务本身也需要处理它)。我觉得不需要任何其他代码要求。只需检查Status
属性以获取任务的完成状态。
从语言设计的角度来看,是否有任何具体原因?有没有其他方法可以将Status
属性设置为取消?
答案 0 :(得分:4)
您只需将调用代码包装在try / catch块中,您要求获得结果,或者等待任务完成 - 这些是抛出异常的情况。例如,创建任务的代码不会抛出该异常。
目前还不清楚替代方案是什么 - 例如:
string x = await GetTaskReturningString();
这里我们从来没有一个变量引用任务,因此我们无法明确检查状态。我们必须使用:
var task = GetTaskReturningString();
string x = await task;
if (task.Status == TaskStatus.Canceled)
{
...
}
...这不仅不太方便,而且还将“发生的事情”代码的处理移动到正常成功路径的中间。
此外,通过使用异常处理取消,如果您有多个操作,则可以将所有处理放在一个catch块中,而不是单独检查每个任务:
try
{
var x = await GetFirstTask();
var y = await GetSecondTask(x);
}
catch (OperationCanceledException e)
{
// We don't care which was canceled
}
同样的论点适用于在一个位置处理取消,无论堆栈中第一次取消发生在哪里 - 如果你有一堆深度异步方法,最深层方法中的取消将导致顶部 - 大多数任务被取消,就像正常的异常传播一样。
答案 1 :(得分:4)
如果您使用CancellationToken
TaskCompletionSource
var tcs = new TaskCompletionSource();
var task = tcs.Task;
tcs.SetCancelled();
除此之外,您只能使用Task
CancellationToken