我很难理解调度程序的异步方法与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响应性方面似乎没有什么改变。
答案 0 :(得分:1)
BeginInvoke
始终是异步的。您要让Dispatcher
(UI线程)在长时间运行的情况下执行此操作,而不会阻塞调用线程。如果您决定改用Invoke
,则在执行您提供的委托完成Dispatcher
之前,调用线程将被阻塞。
BeginInvoke
并不意味着工作是在另一个线程上异步完成的。您想要做的是在另一个任务上启动SomeLongRunningOperation,并使用第二个示例中尝试的异步等待模式将其返回。像这样:
private async void OnEventOccurred(object sender, EventArgs e)
{
await Task.Run(SomeLongRunningOperation());
}
答案 1 :(得分:0)
分配给Dispatcher
的所有代码都在UI线程上运行。将TPL
用于长时间运行的任务,并将Dispatcher
仅用于更新UI。
答案 2 :(得分:0)
这不应该阻止UI线程,对吧?
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
是可能长时间运行的操作,则应在后台线程上执行它。最简单的方法是启动Task
,您可能要等待:
await Task.Run(SomeLongRunningOperation);