我有一个 WPF 应用程序,按下按钮后就会执行以下代码:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
new Thread(
async () =>
{
Action lambda = async () =>
{
await Task.Delay(5000);
MessageBox.Show("Lambda done");
};
await this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, lambda).Task;
MessageBox.Show("Dispatch done");
}).Start();
}
MSDN documentation的DispatcherOperation.Task
说:Gets a Task<TResult> that represents the current operation.
(这不是 Task<TResult>
:/)
所以我认为等待这意味着 MessageBox.Show("Dispatch done");
只会在 lambda 完成后执行。然而,事实并非如此。按下按钮后,就会显示带有“Dispatch done”文本的 MessageBox,并且如预期那样,5 秒后会显示带有“Lambda done”文本的 MessageBox。
有人能解释一下吗?我不明白为什么会发生这种情况。
最佳答案
这一行:
Action lambda = async ...
正在创建一个async void
lambda 而不是 async Task
lambda 。 async void
的(许多)问题之一是没有(简单)方法来判断它何时完成。为此,"avoid async void" is one of the best practices在我关于该主题的 MSDN 文章中。
我没有尝试过,但我怀疑 Dispatcher.BeginInvoke
只能取Action
委托(delegate)(而不是更异步友好的 Func<Task>
),在这种情况下,最好使用 Dispatcher.Invoke
。并通过 Func<Task>
。不过,在我自己的代码中,我避免 Dispatcher
完全;我发现它鼓励更糟糕的代码。而不是Dispatcher
,考虑使用await
和/或Progress<T>
.
关于c# - DispatcherOperation.Task 立即返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35796877/