c# - 通过堆栈的异步/等待行为

标签 c# .net asynchronous async-await

我很好奇 async 的流程是如何在整个堆栈中工作的。在阅读 C# 中的 async 时,您将不断阅读以下内容的某些版本:

If the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then return to your caller immediately; the task will invoke the continuation when it completes.

让我感到困惑的是立即返回调用者部分。在下面的示例中,假设调用了 MethodOneAsync(),执行命中了 MethodOneAsync 中的 await。它会立即返回调用它的方法吗?如果是这样,MethodTwoAsync 是如何执行的?或者它是否继续向下堆栈直到它检测到它实际上被阻止(即 DoDBWorkAsync())然后让出线程?

public static async Task MethodOneAsync()
{
    DoSomeWork();
    await MethodTwoAsync();
}

public static async Task MethodTwoAsync()
{
    DoSomeWork();
    await MethodThreeAsync();
}

public static async Task MethodThreeAsync()
{
    DoSomeWork();
    await DoDBWorkAsync();
}

最佳答案

async方法中await之前的部分是同步执行的。所有 async 方法都是这种情况。

让我们假设 await DoDBWorkAsync() 我们有 await Task.Delay(1000)

这意味着 MethodOneAsync 开始运行,执行 DoSomeWork 并调用 MethodTwoAsync 进而执行 DoSomeWork 调用 MethodThreeAsync 再次执行 DoSomeWork

然后它调用 Task.Delay(1000),返回一个未完成的 Task 并等待它。

await 在逻辑上等同于添加一个延续并将任务返回给调用者,这是 MethodTwoAsync 做同样的事情并返回一个 Task 给调用者和等等。

这样,当根延迟 Task 完成时,所有的延续都可以一个接一个地运行。


如果我们让你的例子更复杂一点:

public static async Task MethodOneAsync()
{
    DoSomeWorkOne();
    await MethodTwoAsync();
    DoMoreWorkOne();
}

public static async Task MethodTwoAsync()
{
    DoSomeWorkTwo();
    await MethodThreeAsync();
    DoMoreWorkTwo();
}

public static async Task MethodThreeAsync()
{
    DoSomeWorkThree();
    await Task.Delay(1000);
    DoMoreWorkThree();
}

这在逻辑上类似于使用延续来执行此操作:

public static Task MethodOneAsync()
{
    DoSomeWorkOne();
    DoSomeWorkTwo();
    DoSomeWorkThree();
    return Task.Delay(1000).
        ContinueWith(_ => DoMoreWorkThree()).
        ContinueWith(_ => DoMoreWorkTwo()).
        ContinueWith(_ => DoMoreWorkOne());
}

关于c# - 通过堆栈的异步/等待行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29502520/

相关文章:

c# - 向 FritzBox 发送 SOAP 请求

.net - 转移.NET互斥锁的所有权

c# - XPath 未按预期工作

ios - 如果在 PushViewController 之后完成,后端完成处理程序会使应用程序崩溃

javascript - promise 是回调的完整替代方案吗?

Django celery 任务 : Newly created model DoesNotExist

c# - StackOverflowException 通过使用具有协变泛型参数的显式接口(interface)实现

c# - 简易喷油器 : RegisterWebApiController failing to suppress DisposableTransientComponent warning

c# - 定义要在构建事件中使用的自定义宏

C# 任务完成后不释放内存