一个表达式Lambda返回表达式的结果。
例如,() => "hi"
返回一个字符串,即使没有return
语句。但是,如果表达式没有返回任何内容,如 () => Console.WriteLine("hi")
,则被视为void
。
但是,对于async
lambdas会有一些诡异的地方。表达式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
有一个重载的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
因此请注意在何处使用它。您可以将鼠标悬停在方法名称上(例如Task.Run
中的Run
),Visual Studio将告诉您它已推断出哪个重载:
是的,它被评估为 async Task
,因为 Task.Delay(n)
的返回类型是 Task
。所以这是一个好的实践方法。
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";
};
}
}
现在缩短的代码看起来就像你的代码。
var fn = async Task (string p1, int p2) =>
{
// await something
};
Task.Run(..)
时,请参考Gabriel Luci的答案。但是我通常会明确指定Task,以便在asp.net core的Map路由方法中更清晰明了。