Task.Factory.FromAsync是否激发创建的任务

本文关键字:创建 任务 Factory FromAsync 是否 Task | 更新日期: 2023-09-27 18:24:17

我有两个任务t1t2,它们是我从一个旧的API生成的,该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&t2)是否被激发:

FromAsync(IAsyncResult, Action<IAsyncResult>):创建一个任务,该任务在指定的IAsyncResult完成时执行结束方法操作。

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

Task.Factory.FromAsync是否激发创建的任务

要比"不,它不会做你想做的事"更明确地回答:

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

是的,Task对象是完全功能性的,并且将执行它的设计任务——等待已经运行的请求结束。

这个保证t2是否总是在成功执行t1之后执行?

不,网络请求已经在运行/超出我们的控制范围,您可以对其进行定义/订购。

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));

如果第一次等待投球,那么第二次就不会被执行。

标题问题的答案是肯定的,一个新的任务开始了,正如使用Resharper的反编译器和.NET参考源所发现的那样,但你永远看不到它。

FromAsync创建一个内部分离的Task,以便在其TaskScheduler上同步运行End方法。您从未见过此任务。您看到的是一个TaskCompletionSource.Task,当End方法正常完成或抛出异常时,它会发出信号。

End方法引发的异常设置在TaskCompletionSource上,因此也设置在您等待的Task上。

从FromAsync返回的Task是由TaskCompletionSource创建的,所以你不能说它是否启动了——当你的操作完成时,它可以被等待并发出信号

因此:

T2将仅在成功完成时运行

  1. T2是在您调用ContinueWith方法之前启动的,因此T1和T2将并行运行。只有在T1成功的情况下才会等待T2
  2. Begin/End内部发生的情况取决于实现,但通常Begin会启动异步操作,End会阻止等待此操作的结果。Web服务和WebClient调用就是这样工作的
  3. T1在调用Begin方法时开始,该方法发生在第一行

编辑

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