[英]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响应性方面似乎没有什么不同。
顾名思义, BeginInvoke
始终是异步的。 您要让Dispatcher
(UI线程)在长时间运行的情况下执行此操作,而不会阻塞调用线程。 如果决定改用Invoke
,则调用线程将被阻塞,直到Dispatcher
执行完您提供的委托为止。
BeginInvoke
并不意味着工作是在另一个线程上异步完成的。 您想要做的是在另一个任务上启动SomeLongRunningOperation,并使用第二个示例中尝试的异步等待模式将其返回。 像这样:
private async void OnEventOccurred(object sender, EventArgs e)
{
await Task.Run(SomeLongRunningOperation());
}
分配给Dispatcher
所有代码都在UI线程上运行。 使用TPL
处理长时间运行的任务,并使用Dispatcher
仅更新UI。
这不应该阻止UI线程,对吗?
SomeLongRunningOperation()
确实将在UI线程上运行并阻塞。 等待BeginInvoke
方法的要点是,一旦SomeLongRunningOperation()
在UI线程上执行完毕,事件处理程序将恢复。 因此,如果在调用BeginInvoke
之后没有执行任何操作,则这里没有必要使用await
关键字。
当您执行以下操作时,将在SomeLongRunningOperation
方法完成之前显示MessageBox
:
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
是可能长时间运行的操作,则应在后台线程上执行它。 最简单的方法是启动Task
,您可能要等待:
await Task.Run(SomeLongRunningOperation);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.