DispatcherOperation.Task 立即返回
DispatcherOperation.Task returning immediately
我有一个 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();
}
DispatcherOperation.Task
的 MSDN documentation 说: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
代表(而不是更异步友好的 Func<Task>
),在这种情况下它可能最好使用 Dispatcher.Invoke
并传递 Func<Task>
。但是,在我自己的代码中,我完全避免了 Dispatcher
;我发现它鼓励更糟糕的代码。考虑使用 await
and/or Progress<T>
.
而不是 Dispatcher
我有一个 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();
}
DispatcherOperation.Task
的 MSDN documentation 说: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
代表(而不是更异步友好的 Func<Task>
),在这种情况下它可能最好使用 Dispatcher.Invoke
并传递 Func<Task>
。但是,在我自己的代码中,我完全避免了 Dispatcher
;我发现它鼓励更糟糕的代码。考虑使用 await
and/or Progress<T>
.
Dispatcher