ane*_*son 4 c# .net-4.0 task-parallel-library c#-4.0
我在我的应用程序中使用任务并行库.我有一个任务(让我们称之为"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?
}
Run Code Online (Sandbox Code Playgroud)
我可以使用TaskCompletionSource,但这看起来很糟糕.还有其他想法吗?
我认为这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;
}
Run Code Online (Sandbox Code Playgroud)
并称之为:
var doSomethingTask = Task.Factory
.StartNew<object>(DoSomething, token)
.WithCleanup(Cleanup);
Run Code Online (Sandbox Code Playgroud)
唯一真正需要注意的是,Task
由于没有非泛型,你不能用普通的旧版本来做TaskCompletionSource
.