如何将任务的已取消状态传播到延续任务

我在我的应用程序中使用任务并行库。 我有一个任务(让我们称之为“DoSomething”)可能被取消。 无论任务是故障,取消还是成功完成,我都会继续执行该任务,执行一些清理工作。

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

这是一个例子:

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,但这看起来很糟糕。 还有其他想法吗?

我认为TaskCompletionSource实际上是这种情况的理想选择。 即您尝试将Task作为完成工作的信号返回,但手动控制该任务何时以及如何报告其状态。 您可以使用这样的扩展方法轻松隐藏此所需的锅炉板:

 public static Task WithCleanup(this Task t, Action> cleanup) { var cleanupTask = t.ContinueWith(cleanup); var completion = new TaskCompletionSource(); 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(DoSomething, token) .WithCleanup(Cleanup); 

唯一真正的警告是,由于没有非通用的TaskCompletionSource ,因此无法使用普通的旧Task执行此TaskCompletionSource