创建表示一系列延续任务的任务



例如,假设我正在编写一个具有以下签名的方法(C#4,因此没有异步关键字):

public Task Refresh();  

它将调用一个方法(也返回一个Task)来执行通信工作,然后运行任务延续以根据检索到的数据更新一些内部状态。 例如:

public Task Refresh()
{
    Task<MyData> commsTask = datasource.LoadData();
    Task handleDataTask = commsTask.ContinueWith( HandleNewData );
    return ?;
}  

如果我返回handleDataTask它的完成状态会正确跟踪"刷新"操作的结果,但它没有正确报告它的启动状态。

我可以将两者包装在新Task.Factory.StartNew中并将它们创建为子任务,但是仅仅为了链接一些任务延续而假脱机新线程似乎很浪费。

当然,有一种简洁有效的方法可以使用TPL来做到这一点吗?

通常,Task.Status仅用于了解最终状态。无论如何,您都不能依赖任务Started,因为该状态可能随时更改。

因此,您返回的任务在完成之前是否具有"奇怪"状态并不重要。只有三种完成的状态(CompletedCanceledFaulted)才重要。

我做了一些进一步的研究,发现了一个类似的SO问题,以及一些博客文章:

没有任务完成源的任务链?

http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx

http://msmvps.com/blogs/jon_skeet/archive/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method.aspx

所以有一个半答案 - 您可以创建一个表示所有子任务的任务实例,而无需假脱机新线程并将它们作为子任务附加:只需使用 TaskCompletionSource。下面的简单示例适用于我上面的问题,没有失败或取消处理:

public Task Refresh()
{
    var refreshTaskSource = new TaskCompletionSource<object>();
    Task<MyData> commsTask = datasource.LoadData();
    Task handleDataTask = commsTask.ContinueWith( HandleNewData );
    handleDataTask.ContinueWith( t => refreshTaskSource.SetResult(null) );
    return refreshTaskSource.Task;
} 

但是,此方法返回的任务现在直接从TaskStatus.WaitingForActivation转换为TaskStatus.RanToCompletion(如果我处理了这些情况,则为错误/取消)。

最新更新