bwa*_*all 3 c# async-await generic-lambda
一个快速的谷歌搜索会告诉你尽可能避免使用async void myMethod()方法。在许多情况下,有办法使之成为可能。我的问题基本上是这个最佳实践的一个分支:
下面的 lambda 表达式的计算结果是什么?
Task.Run( async ()=> await Task.Delay(1000));
Run Code Online (Sandbox Code Playgroud)
如果它变成了,async Task那么我们将遵循最佳实践。
但是如果它评估为async void呢?
表达式 lambdas的文档说,
表达式 lambda 返回表达式的结果
因此,例如,() => "hi"即使没有return语句也返回一个字符串。但是如果表达式没有返回任何东西,比如 in () => Console.WriteLine("hi"),那么它被认为是void。
然而,asynclambdas有一些技巧。该表达式await Task.Delay(1000)本身并没有真正返回任何内容。但是,该语言可以确定,如果您有一个asynclambda,您可能希望它返回一个Task. 所以它会更喜欢那个。
所以这:
Task.Run(async () => await Task.Delay(1000));
Run Code Online (Sandbox Code Playgroud)
等价于这个,如果你用一个命名方法来表达它:
private async Task Wait1000() {
await Task.Delay(1000);
}
Task.Run(Wait1000);
Run Code Online (Sandbox Code Playgroud)
但需要注意的是,可以将asynclambda推断为. 它被认为是唯一的原因,在这里是因为有过载。如果唯一可用的重载带有一个参数,那么它会被推断为,而不会向您发出任何警告。async voidasync TaskTask.Run Func<Task>Actionasync void
例如,这不会产生错误,并且 lambda 被视为async void:
private void RunThisAction(Action action) {
action();
}
RunThisAction(async () => await Task.Delay(1000));
Run Code Online (Sandbox Code Playgroud)
这与将命名async Task方法传递给它的情况不同,后者会导致编译器错误:
private void RunThisAction(Action action) {
action();
}
private async Task Wait1000() {
await Task.Delay(1000);
}
RunThisAction(Wait1000); // 'Task Wait1000()' has the wrong return type
Run Code Online (Sandbox Code Playgroud)
所以在你使用它的地方要小心。您始终可以将鼠标悬停在方法名称上(例如Runin Task.Run),Visual Studio 会告诉您它推断出的重载: