2

我有两个任务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& t2)是否被触发:

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

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

2 回答 2

6

更明确地说,不仅仅是“不,它不会做你想做的事”作为答案:

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

是的,该Task对象功能齐全,并且将执行其设计的功能-等待已经运行的请求结束。

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

不,Web 请求已经在运行/超出您的控制范围以推迟/订购它们。

创建的任务FormAsync不能自行启动。它们IAsyncResult作为参数接收,因此您已经通过调用启动了底层作业/任务/Web 请求BeginSaveChangesWithRetries。这里的任务只是这个遗留异步机制的一个包装器,它允许你等待那些并以新的和好的方式编写你的代码。

要做到这一点,只需编写:

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

如果第一个等待抛出然后第二个不会被执行。

于 2013-07-23T07:27:31.313 回答
1

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

FromAsync 创建一个内部分离的 Task 以在其 TaskScheduler 上同步运行 End 方法。你永远不会看到这个任务。您看到的是一个 TaskCompletionSource.Task,它在 End 方法完成时发出信号,无论是正常完成还是抛出异常。

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

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

所以:

T2 将仅在成功完成后运行

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

编辑

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

于 2013-07-23T07:51:26.110 回答