具有两个等待的异步调用的异步函数,其中第二个需要第一个的结果
Async function with two awaited async calls, where the 2nd needs the results from the first
所以我有一个看起来像这样的函数:
async Task DoSomething() {
var result = await GetDataForAsyncCall2();
if (result != null) {
await AsyncCall2(result.result1, result.result2);
}
}
我的问题是,每当我尝试调用它时,似乎 return 从函数调用 GetDataForAsyncCall2() 之后。但是我想从函数中得到的实际结果是 AsyncCall2.
为什么我的函数会在第一个 await 之后 returning,或者我如何确保第二个 await 在函数 returns 之前 运行?
Why would my function be returning after the first await?
你问这个问题的事实表明你一定对 await
的行为有一些 完全错误的 信念。这就像问为什么 return
returns。 await
是一种 return
。 (就像 yield return
是迭代器块中的一种 return。yield return
和 await
在某种程度上本质上是同一件事;它们都是工作流所在的点returns 给它的调用者,并在将来将该方法的其余部分注册到 运行。)
您可能需要研究一下 await
在 C# 中的实际含义。简而言之,await
表示"if the results of this task are not available then return to my caller so that it can keep working. Pick up at this point some time in the future after the task I'm waiting for is complete.",即异步等待任务完成。
如果这是您在方法中点击的第一个 await ,那么 return 发送给调用者的东西将是代表方法本身的任务,因为现在 它也不完整,调用者可能想等待它。
但这种简短的解释可能还不够。您应该阅读一些有关其工作原理的文章或教程,以便更有效地使用它。
how can I ensure the second await is ran before the function returns?
你不知道。这是设计使然。 Awaits 允许您识别异步工作流中的点,即 (1) 高延迟操作,以及 (2) 必须在 执行其余工作流之前完成操作的位置 。您拥有的等待序列正确地表示了第二个 high-latency 任务对第一个任务的数据依赖性。系统按设计运行。
But the actual result I want from the function is AsyncCall2.
我假设您所追求的 "result" 是一种副作用,因为没有从 AsyncCall2 中提取任何值,并且您从该方法 return 中得到了一个无价值的任务。
这正是您得到的。您的方法 return 是一项任务,并且 该任务将在 AsyncCall2 完成 return 完成的任务 之后的某个时间点标记为已完成。如果您的调用者希望在将来的那个时间异步等待,那么它应该await
returned 任务。
同样:await
是异步工作流中的一个点,我们知道在它之前,任务可能没有完成,而在它之后,它肯定已经完成。
一个你没有问的问题:
Should I solve my problem by synchronously waiting for the high latency operation using .Result
or similar?
没有。这不仅违背了使用 await
来管理延迟的全部目的。它还可能导致您永远等待。有关示例,请参阅 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html。
这些例子很有教育意义;我会 非常 仔细阅读它们,直到您彻底理解 await
的工作原理。
所以我有一个看起来像这样的函数:
async Task DoSomething() {
var result = await GetDataForAsyncCall2();
if (result != null) {
await AsyncCall2(result.result1, result.result2);
}
}
我的问题是,每当我尝试调用它时,似乎 return 从函数调用 GetDataForAsyncCall2() 之后。但是我想从函数中得到的实际结果是 AsyncCall2.
为什么我的函数会在第一个 await 之后 returning,或者我如何确保第二个 await 在函数 returns 之前 运行?
Why would my function be returning after the first await?
你问这个问题的事实表明你一定对 await
的行为有一些 完全错误的 信念。这就像问为什么 return
returns。 await
是一种 return
。 (就像 yield return
是迭代器块中的一种 return。yield return
和 await
在某种程度上本质上是同一件事;它们都是工作流所在的点returns 给它的调用者,并在将来将该方法的其余部分注册到 运行。)
您可能需要研究一下 await
在 C# 中的实际含义。简而言之,await
表示"if the results of this task are not available then return to my caller so that it can keep working. Pick up at this point some time in the future after the task I'm waiting for is complete.",即异步等待任务完成。
如果这是您在方法中点击的第一个 await ,那么 return 发送给调用者的东西将是代表方法本身的任务,因为现在 它也不完整,调用者可能想等待它。
但这种简短的解释可能还不够。您应该阅读一些有关其工作原理的文章或教程,以便更有效地使用它。
how can I ensure the second await is ran before the function returns?
你不知道。这是设计使然。 Awaits 允许您识别异步工作流中的点,即 (1) 高延迟操作,以及 (2) 必须在 执行其余工作流之前完成操作的位置 。您拥有的等待序列正确地表示了第二个 high-latency 任务对第一个任务的数据依赖性。系统按设计运行。
But the actual result I want from the function is AsyncCall2.
我假设您所追求的 "result" 是一种副作用,因为没有从 AsyncCall2 中提取任何值,并且您从该方法 return 中得到了一个无价值的任务。
这正是您得到的。您的方法 return 是一项任务,并且 该任务将在 AsyncCall2 完成 return 完成的任务 之后的某个时间点标记为已完成。如果您的调用者希望在将来的那个时间异步等待,那么它应该await
returned 任务。
同样:await
是异步工作流中的一个点,我们知道在它之前,任务可能没有完成,而在它之后,它肯定已经完成。
一个你没有问的问题:
Should I solve my problem by synchronously waiting for the high latency operation using
.Result
or similar?
没有。这不仅违背了使用 await
来管理延迟的全部目的。它还可能导致您永远等待。有关示例,请参阅 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html。
这些例子很有教育意义;我会 非常 仔细阅读它们,直到您彻底理解 await
的工作原理。