不带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);
我很难理解调度程序的异步方法与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);