4

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

public Task Refresh();  

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

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

    return ?;
}  

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

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

使用 TPL 确实有一种简洁有效的方法吗?

4

2 回答 2

3

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

因此,您返回的任务在完成之前是否处于“奇怪”状态并不重要。只有三个已完成的状态 ( Completed, Canceled, Faulted) 很重要。

于 2012-04-15T12:00:38.937 回答
0

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

没有 TaskCompletionSource 的任务链?

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.WaitingForActivationTaskStatus.RanToCompletion(如果我处理过这些场景,则为故障/取消)。

于 2012-04-16T10:48:23.920 回答