异步void Lambda表达式 [英] Async void lambda expressions

查看:105
本文介绍了异步void Lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

快速的 Google搜索会告诉您避免在可能的情况下使用async void myMethod()方法.在许多情况下,使其成为可能的方式.我的问题基本上是此最佳做法的分支:

A quick google search will tell you to avoid using async void myMethod() methods when possible. And in many cases there are ways to make it possible. My question is basically an offshoot of this best practice:

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

What does the lambda expression below evaluate to?

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

如果它成为async Task,那么我们将遵循最佳实践.

If it becomes an async Task then we are following best practice.

但是如果评估结果为async void怎么办?

But what if it evaluates to async void?

推荐答案

lambda表达式返回表达式的结果

An expression lambda returns the result of the expression

因此,例如,即使没有return语句,() => "hi"也会返回字符串.但是,如果表达式不返回任何内容(如() => Console.WriteLine("hi")中的内容),则将其视为void.

So, for example, () => "hi" returns a string, even though there is no return statement. But if the expression doesn't return anything, like in () => Console.WriteLine("hi"), then it's considered void.

但是async lambdas有一些诡计.表达式await Task.Delay(1000)本身并不真正返回任何内容.但是,该语言可以弄清楚,如果您有一个async lambda,则可能希望它返回一个Task.因此,它会更喜欢.

However there is a bit of trickery with async lambdas. The expression await Task.Delay(1000) doesn't really return anything in itself. However, the language can figure out that if you have an async lambda, you likely want it to return a Task. So it will prefer that.

所以这个:

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

如果您要使用命名方法表示它,则等同于此:

Is equivalent to this, if you were to express it with a named method:

private async Task Wait1000() {
    await Task.Delay(1000);
}
Task.Run(Wait1000);

但是必须注意,可以将async lambdas 推断为async void.在此处被认为是async Task的唯一原因是因为Task.Run Func<Task> 具有重载.如果唯一可用的重载采用了 Action 参数,那么它将被推断为async void,而不会向您发出任何警告.

But it is important to note that async lambdas can be inferred to be async void. The only reason it is considered async Task here is because Task.Run has an overload for Func<Task>. If the only available overload took an Action parameter, then it would be inferred to be async void, without any warning to you.

例如,这不会产生错误,并且lambda被视为async void:

For example, this produces no error and the lambda is treated as async void:

private void RunThisAction(Action action) {
    action();
}
RunThisAction(async () => await Task.Delay(1000));

与您将其传递给名为async Task的方法不同,这将导致编译器错误:

That is different than if you passed it a named async Task method, which would cause a compiler error:

private void RunThisAction(Action action) {
    action();
}
private async Task Wait1000() {
    await Task.Delay(1000);
}
RunThisAction(Wait1000); // 'Task Wait1000()' has the wrong return type

因此请小心在何处使用它.您总是可以将鼠标悬停在方法名称上(例如Task.Run中的Run),Visual Studio会告诉您它推断出了哪个重载:

So be careful where you use it. You can always hover over the method name (like the Run in Task.Run) and Visual Studio will tell you which overload it has inferred:

这篇关于异步void Lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆