我试图绕过异步等待,但是我写了一个小测试,无法理解我得到的结果。
考虑以下代码(WPF应用程序,在MainWindow内部):
private async void Button_Click(object sender, RoutedEventArgs e)
{
Stopwatch l_Stopwatch = new Stopwatch();
Debug.WriteLine("Entering Button_Click...");
l_Stopwatch.Start();
await DoSomethingAsync();
l_Stopwatch.Stop();
Debug.WriteLine("DoSomethingAsync completed in {0}", l_Stopwatch.ElapsedMilliseconds);
l_Stopwatch.Restart();
await DoSomethingElseAsync();
l_Stopwatch.Stop();
Debug.WriteLine("DoSomethingElseAsync completed in {0}", l_Stopwatch.ElapsedMilliseconds);
}
private async Task DoSomethingAsync()
{
Debug.WriteLine("Doing something Async");
await Task.Delay(5000);
}
private async Task DoSomethingElseAsync()
{
await Task.Run((Action)(async () => {
Debug.WriteLine("Doing something else Async");
await Task.Delay(5000);
}));
}
我希望DoSomethingElseAsync在继续之前等待〜5000ms,但是我不断收到以下消息
Entering Button_Click...
Doing something Async
DoSomethingAsync completed in 5005
Doing something else Async
DoSomethingElseAsync completed in 3
因此,在这一点上,我认为有些根本的东西我不了解异步等待方式...
有人能照亮吗?
答案 0 :(得分:3)
问题在这里:
await Task.Run((Action)(async () => {
Debug.WriteLine("Doing something else Async");
await Task.Delay(5000);
}));
您强制转换为Action
代表,该代表不返回任何内容且无法等待(因为Task
返回了Action
,因此没有void
可以等待)。
您可以将代码更改为:
await Task.Run(async () => {
Debug.WriteLine("Doing something else Async");
await Task.Delay(5000);
});
OR
您可以强制转换为Func<Task>
的委托,该委托返回可以等待的Task
:
await Task.Run((Func<Task>)(async () => {
Debug.WriteLine("Doing something else Async");
await Task.Delay(5000);
}));
其他信息:
如果看到编译器生成的代码(SharpLab),您将得到不同之处:
Action
时,编译器会创建AsyncVoidMethodBuilder
Func<Task>
或不强制所有编译器创建时
AsyncTaskMethodBuilder