2012-04-15 29 views
4

例如,让我们说我正在写与下面的签名(C#4所以没有异步关键字)的方法:创建表示一系列连续任务的任务

public Task Refresh(); 

它会调用一个方法(它也返回Task)执行通信工作,然后运行任务延续以基于检索到的数据更新某些内部状态。 e.g:

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

    return ?; 
} 

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

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

当然,有一个整洁有效的方式来与TPL做到这一点?

+0

你为什么关心国家? – svick 2012-04-15 10:26:52

+0

这样的实现匹配方法签名的隐式文档?我不知道,问我的方法的消费者。 “Task.Status”属性可能有100多种用途,我所知道的是我的方法应该返回一个正确跟在它的文档后面的“Task”。 – Tyson 2012-04-15 10:34:57

回答

3

通常,Task.Status仅用于找出有关最终状态。无论如何,你无法依靠Started这个任务,因为这个状态可能会随时改变。

因为这个事实,如果你返回的任务有一个“奇怪”的状态,直到它完成,这并不重要。只有三个完成状态(Completed,Canceled,Faulted)很重要。

+0

我同意3个最终状态是重要的。但是不能保证最终的任务将会运行,所以通过返回链中的最终任务,你会冒着代表整个操作返回的'Task'实例永远停留在'WaitingForActivation'中的风险。我没有在示例中加入它,但如果任务先前的任务被取消,那么Task Continuations可能不运行。 – Tyson 2012-04-16 10:55:45

+1

@Tyson,如果先行任务被取消,那么继续任务通常会运行。如果使用TaskContinuationOptions来修改它,则继续也会被取消。因此,它不会被卡住在'WaitingForActivation'状态(除非前件包含无限循环或死锁)。 – svick 2012-04-16 12:10:20

+0

@svick嗯......我现在找不到参考资料,但我记得看到一个任务延续未运行的例子。虽然现在我想虽然它没有运行,但它仍然像你说的那样直接进入'Cancelled'状态。我不知道,为了表示整个序列而返回最后的任务还是很麻烦。 – Tyson 2012-04-16 12:26:00

0

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

Task chaining without 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

所以就有了一半的答案 - 你可以创建一个代表所有子任务的Task实例,无需将新线程作为子任务进行后台处理:只需使用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(或存在故障/取消,如果我有处理这些场景) 。