不带await的Dispatcher.BeginInvoke()还是异步执行的吗?

Is Dispatcher.BeginInvoke() without await still executed asynchronous?

我很难理解调度程序的异步方法与async/await之间的联系。

在我的例子中,我有一个在调度程序上执行操作的事件处理程序:

 private void OnEventOccurred(object sender, EventArgs e)
 {
     someControl.Dispatcher.BeginInvoke(DispatcherPriority.Background, SomeLongRunningOperation());
 }

这应该不会阻塞 UI 线程,对吧?至少在我们的应用程序中感觉是这样。与带async/await的版本有什么区别?

 private async void OnEventOccurred(object sender, EventArgs e)
 {
     await someControl.Dispatcher.BeginInvoke(DispatcherPriority.Background, SomeLongRunningOperation());
 }

这也有效,并且在 UI 响应能力方面似乎没有什么不同。

分配给 Dispatcher 的所有代码都在 UI 线程上运行。使用 TPL 执行长 运行 任务,使用 Dispatcher 仅更新 UI。

BeginInvoke 顾名思义总是异步的。您要求 Dispatcher(UI 线程)执行此操作,在您的情况下为长 运行,而不会阻塞调用线程。如果您决定改用 Invoke,调用线程将被阻塞,直到 Dispatcher 执行完您提供的委托。

BeginInvoke 并不意味着工作是在不同的线程上异步完成的。您想要做的是在不同的任务上启动此 SomeLongRunningOperation 并 return 它使用您在第二个示例中尝试的异步等待模式。像这样:

 private async void OnEventOccurred(object sender, EventArgs e)
 {
     await Task.Run(SomeLongRunningOperation());
 }

This should not block the UI thread, right?

SomeLongRunningOperation() 确实会 运行 打开并阻塞 UI 线程。等待 BeginInvoke 方法的意义在于,一旦 SomeLongRunningOperation() 在 UI 线程上完成执行,您的事件处理程序就会恢复。因此,如果您在调用 BeginInvoke 后不执行任何操作,则没有必要在此处使用 await 关键字。

当您执行以下操作时,MessageBox 将在 SomeLongRunningOperation 方法完成之前显示:

private void OnEventOccurred(object sender, EventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(SomeLongRunningOperation));
    MessageBox.Show("SomeLongRunningOperation will be executed eventually!");
}

并且当你执行以下操作时,它将在 SomeLongRunningOperation 完成后显示:

private async void OnEventOccurred(object sender, EventArgs e)
{
    await Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(SomeLongRunningOperation));
    MessageBox.Show("SomeLongRunningOperation has been executed!");
}

因此,如果您不打算在方法返回后在事件处理程序中执行任何操作,那么等待对 BeginInvoke 的调用是没有意义的。

请注意,这里的所有内容 运行 都在同一个线程上。如果 SomeLongRunningOperation 是一个潜在的 long-运行ning 操作,您应该在后台线程上执行它。最简单的方法是启动一个 Task,您可以等待它:

await Task.Run(SomeLongRunningOperation);