C# 异步void lambda表达式
一个快捷键会告诉您尽可能避免使用C# 异步void lambda表达式,c#,async-await,generic-lambda,C#,Async Await,Generic Lambda,一个快捷键会告诉您尽可能避免使用async void myMethod()方法。在很多情况下,都是这样。我的问题基本上是这个最佳实践的一个分支: 下面的lambda表达式的计算结果是什么 Task.Run( async ()=> await Task.Delay(1000)); 如果它成为一个异步任务,那么我们将遵循最佳实践 但是如果它的计算结果为async void?是的,它的计算结果为async Task,因为Task.Delay(n)的返回类型为Task。因此,这是一种良好的做法
async void myMethod()
方法。在很多情况下,都是这样。我的问题基本上是这个最佳实践的一个分支:
下面的lambda表达式的计算结果是什么
Task.Run( async ()=> await Task.Delay(1000));
如果它成为一个异步任务
,那么我们将遵循最佳实践
但是如果它的计算结果为
async void
?是的,它的计算结果为async Task
,因为Task.Delay(n)
的返回类型为Task
。因此,这是一种良好的做法
:
因此,上述代码可以缩短为:
public Form1()
{
InitializeComponent();
button1.Click += async (sender, e) =>
{
await Task.Delay(1000);
textBox1.Text += "\r\nControl returned to Click event handler.\n";
};
}
}
现在缩短的代码看起来像您的代码。对于表达式,lambdas说
表达式lambda返回表达式的结果
因此,例如,()=>“hi”
返回一个字符串,即使没有return
语句。但是如果表达式没有返回任何内容,比如在()=>Console.WriteLine(“hi”)
中,那么它被认为是无效的
然而,async
lambdas有一点小技巧。表达式wait Task.Delay(1000)
本身并没有返回任何内容。但是,该语言可以发现,如果您有一个async
lambda,您可能希望它返回一个任务
。因此,它更愿意这样做
因此:
Task.Run(async () => await Task.Delay(1000));
如果要使用命名方法表示,则与此等效:
private async Task Wait1000() {
await Task.Delay(1000);
}
Task.Run(Wait1000);
但需要注意的是,async
lambda可以推断为async void
。这里认为它是异步任务
的唯一原因是Task.Run
。如果唯一可用的重载包含一个参数,那么它将被推断为async void
,而不会向您发出任何警告
例如,这不会产生错误,并且lambda被视为异步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
所以在使用它的地方要小心。您可以始终将鼠标悬停在方法名称上(如任务中的运行
。运行
),Visual Studio将告诉您它推断出的重载:
似乎有一些解释。在您的特定情况下,它将解析为一个异步函数,返回一个任务
,因此遵循最佳实践。回答好,图片好,cows很棒。
private void RunThisAction(Action action) {
action();
}
private async Task Wait1000() {
await Task.Delay(1000);
}
RunThisAction(Wait1000); // 'Task Wait1000()' has the wrong return type