2011-01-25 68 views
4

我在我的应用程序中使用了任务并行库。我有一个任务(我们称之为“DoSomething”),它可能被取消。无论任务是故障,取消还是成功完成,我都会继续执行一些清理任务。如何将任务的已取消状态传播到继续任务

在启动此任务的代码中,我想返回其状态(故障,取消,运行完成)反映DoSomething任务状态的Task对象,但重要的是我返回的此任务不反映此状态直到执行继续任务。

下面是一个例子:

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,但似乎缺憾。任何其他想法?

+0

发表了一个答案,但有一个顺利。研究一个更加正确的解决方案,我很快就会有这个解决方案。 – 2011-01-28 17:38:17

+0

好的......问题时间:你需要等待()返回的任务吗? – 2011-01-28 18:10:20

回答

7

我认为TaskCompletionSource实际上是这种情况下的理想选择。即您试图返回Task作为完成工作的信号,但手动控制任务何时以及如何报告其状态。你可以很容易隐藏与扩展方法是这样要求这个锅炉板:

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); 

唯一真正需要注意的是,你不能做到这一点普通旧Task因为没有非通用TaskCompletionSource