我有两个任务t1
和t2
,我使用设计有开始/结束异步模型的旧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
一样)?答案 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仅在成功完成时运行
修改强>
如果您调用接受函数而不是IAsyncResult的FromAsync重载,则事情不会改变,因为FromAsync立即调用函数并启动操作