C# c中异步函数的差异#

C# c中异步函数的差异#,c#,asynchronous,task,C#,Asynchronous,Task,我在中阅读了有关异步模式的内容,并决定采纳Jon的建议,对异步代码进行反编译,以了解实际情况。我遇到了两种情况,这让我有点困惑,为什么它们是不同的 考虑这两个功能: public static async Task<string> GetValue(){ int count = 0; count++; string g = "asdf"; var r = Task.FromResult<string> ("hello"); retu

我在中阅读了有关异步模式的内容,并决定采纳Jon的建议,对异步代码进行反编译,以了解实际情况。我遇到了两种情况,这让我有点困惑,为什么它们是不同的

考虑这两个功能:

public static async Task<string> GetValue(){
    int count = 0;
    count++;
    string g = "asdf";
    var r = Task.FromResult<string> ("hello");
    return g;
}
公共静态异步任务GetValue(){
整数计数=0;
计数++;
字符串g=“asdf”;
var r=Task.FromResult(“你好”);
返回g;
}

公共静态异步任务GetValue(){
整数计数=0;
计数++;
字符串g=“asdf”;
var r=wait Task.FromResult(“你好”);
返回g;
}
现在我希望代码输出相同的IL,因为它们都是异步函数,所以需要一个状态机。但令我惊讶的是,C#编译器确实创建了状态机。在这两种情况下,状态机都遵循与预期完全相同的代码,除了在第一个代码块中,它实际上没有在机器中保存任何信息。在第二种情况下,它确实存储了所有变量


编译器决定不将变量保存在状态机中,并根据
await
keword公开两个不同的代码路径,这是有原因的吗?

第一个应该给您一个关于不是真正异步(“将同步运行”)的警告,因为其中没有
await

因此存在一个状态机,因为您将其标记为
async
,可以使用
wait
调用它


但是没有要保存的信息,因为在使用它的方法中没有
wait

第一个应该给你一个关于不是真正异步的警告(“…将同步运行”),因为那里没有
wait

因此存在一个状态机,因为您将其标记为
async
,可以使用
wait
调用它


但是没有要保存的信息,因为在使用它的方法中没有
wait

我认为这种差异是由于缺少
wait
操作符造成的。如果没有
wait
,编译器会将您的代码视为同步代码。没有理由使用
状态机

因此本质上,它创建了
状态机
,正如它所期望的
异步
代码一样,但实际上并没有实现任何
异步
的代码。把它当作一个空容器

设置代码初始化用于表示状态的状态机 异步方法,然后使用对 状态机上的辅助MoveNext方法。这个国家机器 类型保存异步方法的状态,允许该状态 如有必要,可跨异步等待点持久化

在第二个示例中,状态机保存您的数据,因为
wait
。这会触发状态机通过多个
等待点
保存数据。因为另一个例子不包含wait,所以它仍然是空的。它只创建了状态机,因为您将其修饰为
async
,尽管它实际上不是


这是一篇关于此事的小摘录,希望能有所帮助。

我相信这种差异是由于缺少
wait
操作员造成的。如果没有
wait
,编译器会将您的代码视为同步代码。没有理由使用
状态机

因此本质上,它创建了
状态机
,正如它所期望的
异步
代码一样,但实际上并没有实现任何
异步
的代码。把它当作一个空容器

设置代码初始化用于表示状态的状态机 异步方法,然后使用对 状态机上的辅助MoveNext方法。这个国家机器 类型保存异步方法的状态,允许该状态 如有必要,可跨异步等待点持久化

在第二个示例中,状态机保存您的数据,因为
wait
。这会触发状态机通过多个
等待点
保存数据。因为另一个例子不包含wait,所以它仍然是空的。它只创建了状态机,因为您将其修饰为
async
,尽管它实际上不是


这是一个关于这个问题的小摘录,希望能有所帮助。

只需要捕获
wait
表达式可见的变量:

public static async Task Method() {
    int a=3;
    Console.WriteLine(a);
    {
        int b=3;
        Console.WriteLine(b);
    }
    await Task.FromResult(true);
}

例如,在捕获的
a
上面的代码中,
b
未捕获。因此,如果不使用
await
,则无需捕获任何内容。

只需捕获
await
表达式可见的变量:

public static async Task Method() {
    int a=3;
    Console.WriteLine(a);
    {
        int b=3;
        Console.WriteLine(b);
    }
    await Task.FromResult(true);
}

例如,在捕获的
a
上面的代码中,
b
未捕获。因此,如果不使用
await
,则无需捕获任何内容。

尽管没有wait,并且创建了状态机,但它却决定不跟踪任何内容,这似乎有点奇怪,我想知道为什么编译器在执行所有异步代码时会经历所有麻烦,然后忽略存储任何内容。我理解为什么状态机是为了捕获异常而存在的,但不确定为什么它会跳过保存。是否存在性能影响或其他我看不到的问题?从外部看,它仍然是异步的。为什么编译器不能实现状态机?它必须以某种方式处理等待呼叫。这也是有道理的。我只是想知道为什么会有if(!await关键字)的特殊情况不要把任何东西推到状态机上为什么还要这样branch@dbarnes因为
状态机
将使用
await
操作符为您的
async
方法保存持久性。@dbarnes-您的代码中没有
if(…)
,我没有得到您的上一个common