c# - 调用链中的异步等待分配

标签 c# .net-core task

我试图更好地理解由于编译器为 C# 中的异步等待生成代码而发生的堆分配。

考虑以下代码:

static async Task OneAsync()
{
    Console.WriteLine("OneAsync: Start");
    await TwoAsync();
    Console.WriteLine("OneAsync: End");
}

static async Task TwoAsync()
{
    Console.WriteLine("TwoAsync: Start");
    await ThreeAsync();
    Console.WriteLine("TwoAsync: End");
}

static async Task ThreeAsync()
{
    Console.WriteLine("ThreeAsync: Start");
    var c = new HttpClient();
    var content = await c.GetStringAsync("http://google.com");
    Console.WriteLine("Content:" + content.Substring(0, 10));
    Console.WriteLine("ThreeAsync: End");
}

来自 ILSpy From ILSpy

这里我们有 3 种 AsyncStateMachine 结构类型(一种用于 OneAsync,一种用于 TwoAsync,一种用于 ThreeAsync) 由编译器生成。

能否请您确认我的假设是否正确?

  • 调用 OneAsync 方法(依次调用链,直到 ThreeAsync),将导致 3 AsyncStateMachine struct types 要放在上?

  • 如果我没有在 ThreeAsync 方法中使用 HttpClient 而只是从它返回 Task.CompletedTask,那么会有 2 个 AsyncStateMachine 结构类型(一种用于 OneAsync,一种用于 TwoAsync)。在这种情况下,不会为 AsyncStateMachine 结构类型分配堆,因为整个调用链会同步执行吗?

最佳答案

无论哪种方式,您都会有三个状态机,因为存在三个异步方法。编译器创建的 stub 总是创建一个状态机。如果您将 ThreeAsync 更改为没有 async 修饰符,而是只编写一个返回已完成任务的常规 方法,您将有两个.

关于堆分配,您是对的:所涉及的等待者在检查时都已完成,因此不需要安排继续。这意味着除了(可能)任务之外,不需要堆分配任何东西。当您返回纯 Task 并且任务总是成功时,我希望也使用缓存的已完成任务。

关于c# - 调用链中的异步等待分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50412177/

相关文章:

c# - Windows Azure 结束连接并返回 324 错误代码

c# - 系统.ServiceModel.Web .NET Core

c# - 在集成测试中设置环境

.net-core - 我为 dotnet CLI 安装了一个工具,为什么命令工具列表没有显示它?

linux - 尝试使用 "current"宏时出现编译错误

c# - 了解异步/等待和 Task.Run()

C# 属性访问器错误

c# - 将 Excel 连接到 .Net Core v1.1 OData v4 时出现异常 添加至少一种媒体类型?

c# - 使用LINQ将XML解析成Dictionary

android - Phonegap 后台任务计划程序 (Android)