如何将任务的取消状态传播到后续任务 [英] How to propagate a Task's Canceled status to a continuation task

查看:127
本文介绍了如何将任务的取消状态传播到后续任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用任务并行库在我的应用程序。我有一个任务(姑且称之为DoSomething的),这可能会被取消。任务是否出现故障,取消或成功完成,我必须连接到该任务,执行一些清理工作的延续。

I am using the Task Parallel Library in my application. I have a Task (let's call it "DoSomething") which may be canceled. Whether the task is faulted, canceled, or completes successfully, I have a continuation attached to that task which performs some cleanup.

在code,会启动这个任务,我想回到一个任务对象,其状态(故障,取消运行完成)反映了DoSomething的任务的状态,但它是这个任务我返回不能反映很重要这种状态,直到继续执行任务。

In the code that launches this task, I want to return a Task object whose status (faulted, canceled, ran to completion) reflects the status of the DoSomething task, however it's important that this task I return not reflect this status until the continuation task executes.

下面是一个例子:

public Task Start(CancellationToken token)
{
    var doSomethingTask = Task.Factory.StartNew(DoSomething
                                                , token);

    var continuationTask = doSomethingTask.ContinueWith
                (
                 (antecedent) =>
                     {
                         if (antecedent.IsFaulted || antecedent.IsCanceled)
                         {
                             //Do failure-specific cleanup
                         }

   //Do general cleanup without regard to failure or success
                      }
                 );

//TODO: How do I return a Task obj which Status reflect the status of doSomethingTask,
//but will not transition to that status until continuationTask completes?
}

我可以用一个TaskCompletionSource,但这似乎缺憾。任何其他的想法?

I could use a TaskCompletionSource, but that seems kludgy. Any other ideas?

推荐答案

我觉得 TaskCompletionSource 其实是非常适合这个场景。即你试图返回工作为你的工作完成的信号,但手动控制的时间和方式的任务报告其状态。你可以很容易隐藏需要这种有像这样的扩展方法的锅炉板:

I think that TaskCompletionSource is actually ideal for this scenario. I.e. you are trying to return a Task as a signal of completion of your work, but manually control when and how that task reports its status. You could easily hide the boiler plate required for this with an extension method like this:

public static Task<T> WithCleanup<T>(this Task<T> t, Action<Task<T>> cleanup) {
    var cleanupTask = t.ContinueWith(cleanup);
    var completion = new TaskCompletionSource<T>();
    cleanupTask.ContinueWith(_ => {
        if(t.IsCanceled) {
            completion.SetCanceled();
        } else if(t.IsFaulted) {
            completion.SetException(t.Exception);
        } else {
            completion.SetResult(t.Result);
        }
    });
    return completion.Task;
}

和调用它是这样的:

var doSomethingTask = Task.Factory
  .StartNew<object>(DoSomething, token)
  .WithCleanup(Cleanup);

唯一真正需要注意的是,你不能用普通的老式工作,因为没有非泛型 TaskCompletionSource

The only real caveat is that you can't do this with plain old Task since there is no non-generic TaskCompletionSource.

这篇关于如何将任务的取消状态传播到后续任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆