8

一个快速的谷歌搜索会告诉你尽可能避免使用async void myMethod()方法。并且在许多情况下,有办法使之成为可能。我的问题基本上是这个最佳实践的一个分支:

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

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

如果它变成了,async Task那么我们将遵循最佳实践。

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

4

2 回答 2

12

表达式 lambdas的文档说,

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

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

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

所以这:

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

相当于这个,如果你用命名方法来表达它:

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

但重要的是要注意asynclambda可以推断为async void. 在这里考虑它的唯一原因async Task是因为. 如果唯一可用的重载带有一个参数,那么它将被推断为,而不会向您发出任何警告。Task.Run Func<Task>Actionasync 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

所以要小心你在哪里使用它。您始终可以将鼠标悬停在方法名称上(例如Runin Task.Run),Visual Studio 会告诉您它推断出的重载:

在此处输入图像描述

于 2020-05-15T21:09:25.920 回答
4

是的,它被评估为async Task因为Task.Delay(n)返回类型为Task. 所以这是一个很好的做法。

此外,还有 msdn 示例,但它有点冗长

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += async (sender, e) =>
        {
            await ExampleMethodAsync();
            textBox1.Text += "\r\nControl returned to Click event handler.\n";
        };
    }

    private async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

所以上面的代码可以缩短为:

public Form1()
{
    InitializeComponent();
    button1.Click += async (sender, e) =>
    {
        await Task.Delay(1000);
        textBox1.Text += "\r\nControl returned to Click event handler.\n";
        };
    }
}

现在缩短的代码看起来像你的代码。

于 2020-05-15T20:35:04.963 回答