【问题标题】:Is there any other way to set Task.Status to Cancelled有没有其他方法可以将 Task.Status 设置为 Canceled
【发布时间】:2014-12-17 13:15:15
【问题描述】:

好的,我了解如何使用CancellationTokenSource 取消任务。在我看来,Task 类型“某种”会自动处理此异常——它将Task 的Status 设置为已取消。

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

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

【问题讨论】:

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


    【解决方案1】:

    如果您使用TaskCompletionSource 创建任务,则可以在没有CancellationToken 的情况下将任务的状态设置为取消

    var tcs = new TaskCompletionSource();
    var task = tcs.Task;
    tcs.SetCancelled();
    

    除此之外,您只能使用CancellationToken 取消正在运行的Task

    【讨论】:

    • 有趣...我会看看这个,虽然乔恩的回答改变了我的想法。
    • @Simon Jon Skeet 的回答当然是正确的。这大概是The XY problem的情况@
    • @l3arnon - 太棒了 - 这正是我的问题! Y 问题,啊我的意思是 X..eh :)
    【解决方案2】:

    您只需将调用代码包装在请求结果或等待任务完成的 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
    }
    

    同样的论点适用于在堆栈中第一次取消发生的一个位置处理取消 - 如果您有一个深度堆栈的异步方法,最深方法中的取消将导致顶部 -大多数任务被取消,就像正常的异常传播一样。

    【讨论】:

    • 谢谢。您答案的第二部分清楚(并解释)了设计决策和推理。现在我同意 try/catch 方法可能比我最初的想法更干净。但是,我不明白为什么我不必将调用代码包装在 try 块中 - 如果我不这样做,OperationCancelledException 会导致应用程序崩溃?
    • @Simon:我的意思是,开始任务的代码不是需要被包装的——只有等待结果的代码......即使这样, 只在顶级。会澄清的。
    • 我想我理解这个场景!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2020-02-22
    • 2018-01-21
    • 1970-01-01
    相关资源
    最近更新 更多