Task.Factory.FromAsync是否会触发创建的任务?

时间:2013-07-23 07:16:14

标签: c# async-await

我有两个任务t1t2,我使用设计有开始/结束异步模型的旧API生成,如下所示。但是我严格想要一个接一个地运行它们。 (这是Azure表存储API)

Task<DataServiceResponse> t1 = Task.Factory.FromAsync(ctx1.BeginSaveChangesWithRetries(null, null), r => ctx1.EndSaveChangesWithRetries(r));
Task<DataServiceResponse> t2 = Task.Factory.FromAsync(ctx2.BeginSaveChangesWithRetries(null, null),  r => ctx2.EndSaveChangesWithRetries(r));

await t1.ContinueWith(t => t2, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.NotOnCanceled);

我阅读了FromAsync文档,但没有说明这些任务(t1&amp; t2)是否会被触发:

  

FromAsync(IAsyncResult, Action<IAsyncResult>):   创建一个Task,在指定的IAsyncResult完成时执行end方法操作。

  • 在成功执行t2之后,此保证t1是否会始终执行
  • 我相信这段代码会调用开始/结束对的Begin...方法。通常是在end方法中完成的操作(在这种情况下,向Azure Service发出HTTP请求)? (我不太熟悉开始/结束实现的内容)
  • t1语句之前await是否开始(或已安排)(就像我使用Task.Factory.StartNew一样)?

2 个答案:

答案 0 :(得分:6)

更明确的不仅仅是'不,它不会做你想做的'作为答案:

  

Task.Factory.FromAsync是否会触发创建的任务?

是的Task对象完全正常运行,并且会执行它的设计目的 - 等待已经运行的请求结束。

  

这是否保证t2在成功执行t1后始终执行?

没有网络请求已经在运行/输出我们的控制权来进行deffer /订购。

FormAsync创建的任务无法自行启动。他们收到IAsyncResult作为参数,因此您已通过调用BeginSaveChangesWithRetries启动了基础作业/任务/ Web请求。这里的任务只是这个遗留异步机制的包装器,允许您等待它们并以新的方式编写代码。

要做到这一点很简单,只需写下:

await Task.Factory.FromAsync(ctx1.BeginSaveChangesWithRetries(null, null), r => ctx1.EndSaveChangesWithRetries(r));
await Task.Factory.FromAsync(ctx2.BeginSaveChangesWithRetries(null, null),  r => ctx2.EndSaveChangesWithRetries(r));

如果第一次等待抛出,那么第二次不会被执行。

答案 1 :(得分:1)

标题问题的答案是肯定的,启动了一个新的任务,使用Resharper的反编译器和.NET参考源,但你永远不会看到它。

FromAsync创建一个内部分离的Task,以在其TaskScheduler上同步运行End方法。你永远不会看到这个任务。你看到的是一个TaskCompletionSource.Task,它在End方法结束时发出信号,通常是通过抛出异常来发出信号。

End方法抛出的异常在TaskCompletionSource上设置,因此是您等待的任务。

从FromAsync返回的任务是由TaskCompletionSource创建的,所以你不能说它是否已经启动 - 它可以在你的操作完成时等待和发出信号

所以:

T2仅在成功完成时运行

  1. 在您调用ContinueWith方法之前启动T2,因此T1和T2将并行运行。只有T1成功,才会等待T2。
  2. Begin / End内部发生的事情取决于实现,但通常Begin会启动异步操作而End块会等待此操作的结果。 Web服务和WebClient调用以这种方式工作。
  3. T1在您调用Begin方法时启动,该方法发生在第一行
  4. 修改

    如果您调用接受函数而不是IAsyncResult的FromAsync重载,则事情不会改变,因为FromAsync立即调用函数并启动操作