简体   繁体   English

Dispatcher.BeginInvoke()是否仍在异步执行?

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

I have a hard time understanding the connection between the asynchrnous methods of the dispatcher and async/await. 我很难理解调度程序的异步方法与async / await之间的联系。

In my case I have an event handler that executes an operation on the dispatcher: 在我的情况下,我有一个事件处理程序,该事件处理程序在调度程序上执行操作:

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

This should not block the UI thread, right? 这不应该阻止UI线程,对吗? At least it feels like it in our application. 至少在我们的应用程序中感觉像。 What is the difference to the version with async/await? 与使用async / await的版本有什么区别?

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

This also works and doesn't seem to make a difference in terms of UI responsiveness. 这也有效,并且在UI响应性方面似乎没有什么不同。

BeginInvoke as the name suggests is always asynchronous. 顾名思义, BeginInvoke始终是异步的。 You're asking the Dispatcher (UI thread) to perform this operation, in your case long running, without blocking the calling thread. 您要让Dispatcher (UI线程)在长时间运行的情况下执行此操作,而不会阻塞调用线程。 If you decided to use the Invoke instead, the calling thread gets blocked until the Dispatcher is done with executing the delegate you provided. 如果决定改用Invoke ,则调用线程将被阻塞,直到Dispatcher执行完您提供的委托为止。

BeginInvoke does not imply that the work is done asynchronously on a different thread. BeginInvoke并不意味着工作是在另一个线程上异步完成的。 What you would want to do is start this SomeLongRunningOperation on a different task and return it using the async await pattern as you tried in the second example. 您想要做的是在另一个任务上启动SomeLongRunningOperation,并使用第二个示例中尝试的异步等待模式将其返回。 Something like this: 像这样:

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

All the code assign to Dispatcher runs on UI thread. 分配给Dispatcher所有代码都在UI线程上运行。 Use TPL for long running tasks and Dispatcher to update UI only. 使用TPL处理长时间运行的任务,并使用Dispatcher仅更新UI。

This should not block the UI thread, right? 这不应该阻止UI线程,对吗?

SomeLongRunningOperation() will indeed run on and block the UI thread. SomeLongRunningOperation()确实将在UI线程上运行并阻塞。 The point of awaiting the BeginInvoke method is that your event handler will resume once SomeLongRunningOperation() has finished executing on the UI thread. 等待BeginInvoke方法的要点是,一旦SomeLongRunningOperation()在UI线程上执行完毕,事件处理程序将恢复。 So if you don't do anything after the call the BeginInvoke , there is no point of using the await keyword here. 因此,如果在调用BeginInvoke之后没有执行任何操作,则这里没有必要使用await关键字。

When you do the following, the MessageBox will be displayed before the SomeLongRunningOperation method has finished: 当您执行以下操作时,将在SomeLongRunningOperation方法完成之前显示MessageBox

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

And when you do the following, it will be display after SomeLongRunningOperation has finished: 当您执行以下操作时,它将在SomeLongRunningOperation完成后显示:

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

So it's pointless to await the call to BeginInvoke if you don't intend to anything in your event handler after the method has returned. 因此,如果在方法返回后不打算在事件处理程序中进行任何操作,则等待对BeginInvoke的调用是没有意义的。

Note that everything runs on the same thread here though. 注意这里所有的东西都在同一个线程上运行。 If SomeLongRunningOperation is a potentially long-running operation, you should execute it on a background thread. 如果SomeLongRunningOperation是可能长时间运行的操作,则应在后台线程上执行它。 The easiest way to do this would be to start a Task , which you may await: 最简单的方法是启动Task ,您可能要等待:

await Task.Run(SomeLongRunningOperation);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM