有没有其他方法可以将Task.Status设置为Canceled

时间:2014-12-17 13:15:15

标签: c# .net task-parallel-library cancellation cancellationtokensource

好的,所以我了解如何使用CancellationTokenSource取消任务。在我看来,Task类型"类型"自动处理此异常 - 它将Task' s Status设置为已取消。

现在你仍然需要处理OperationCancelledException。否则异常会冒泡到Application.UnhandledException。 Task本身识别它并在内部进行一些处理,但是你仍然需要将调用代码包装在try块中以避免未处理的异常。有时,这似乎是不必要的代码。如果用户按下取消,则取消Task(显然任务本身也需要处理它)。我觉得不需要任何其他代码要求。只需检查Status属性以获取任务的完成状态。

从语言设计的角度来看,是否有任何具体原因?有没有其他方法可以将Status属性设置为取消?

2 个答案:

答案 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