c# - 异步 void lambda 表达式

标签 c# async-await generic-lambda

快速google search会告诉你避免使用 async void myMethod()可能的方法。并且在很多情况下有 ways to make it possible .我的问题基本上是这个最佳实践的一个分支:

下面的 lambda 表达式的计算结果是什么?

Task.Run( async ()=> await Task.Delay(1000));

如果它变成 async Task那么我们正在遵循最佳实践。

但是如果它评估为 async void 呢? ?

最佳答案

The documentation对于表达式 lambdas 说,

An expression lambda returns the result of the expression



因此,例如,() => "hi"返回一个字符串,即使没有 return陈述。但是如果表达式没有返回任何东西,比如 () => Console.WriteLine("hi") , 那么它被认为是 void .

然而,async 有一些技巧。 lambda 。表达式 await Task.Delay(1000)本身并没有真正返回任何东西。但是,如果您有 async,语言可以计算出lambda,您可能希望它返回 Task .所以它会更喜欢那个。

所以这:
Task.Run(async () => await Task.Delay(1000));

等价于这个,如果你用一个命名方法来表达它:
private async Task Wait1000() {
    await Task.Delay(1000);
}
Task.Run(Wait1000);

但需要注意的是async lambda 表达式可以推断为 async void .它被认为是唯一的原因 async Task这是因为 Task.Run has an overload for Func<Task> .如果唯一可用的过载采用 Action 参数,则推断为 async void ,对你没有任何警告。

例如,这不会产生错误并且 lambda 被视为 async void :
private void RunThisAction(Action action) {
    action();
}
RunThisAction(async () => await Task.Delay(1000));

这与传递一个命名的 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 中的 Task.Run ),Visual Studio 会告诉您它推断出的重载:

enter image description here

关于c# - 异步 void lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61827597/

相关文章:

c# - 库应该公开辅助类吗?

android - 使用 Kotlin Coroutine 从调用挂起函数的普通函数返回值

javascript - 我的 javascript Async Await api 请求返回一个奇怪的对象

c++ - 通用 lambda 的元数

c++ - std::visit 的 C++17 示例中令人困惑的模板

c# - GetWindowText() 函数并非始终正确执行

c# - 将具有相同名称的字段映射到自动映射器中的不同字段

c# - 在 C# WinForms 中为 Listbox/ListView 行的部分着色的方法?

javascript - 如何在异步 forEach 循环中添加延迟

c++ - 如何获取通用lambda的返回类型和参数类型?