简体   繁体   English

在主线程上执行异步任务的最佳方法

[英]Best way to execute asynchronous task on main thread

I would like to know what is the best asynchronous way to execute a task on the main thread of a .NET application (in a ViewModel to be precise). 我想知道在.NET应用程序的主线程上执行任务的最佳异步方式是什么(准确地说是在ViewModel中)。 Is Dispatcher.BeginInvoke still valid nowadays or does it exist a better way to do that ? Dispatcher.BeginInvoke现在仍然有效还是存在更好的方法呢?

BeginInvoke is very low-level; BeginInvoke非常低级; there's always a better approach available. 总有一种更好的方法可供选择。

In most cases, you can use async / await to kick off an asynchronous operation from the UI thread, and automagically return to the UI thread to display results. 在大多数情况下,您可以使用async / await从UI线程启动异步操作,并自动返回UI线程以显示结果。 By default, the UI context is captured by await and used to resume the async method after the awaited operation completes. 默认情况下, await捕获UI上下文,并在等待操作完成后用于恢复async方法。 (I describe this in more detail on my blog ). (我在我的博客上更详细地描述了这一点)。

If you need to display progress reports from your UI, the best option is the IProgress<T> / Progress<T> types, which again do all the thread marshalling for you. 如果您需要从UI显示进度报告,最好的选项是IProgress<T> / Progress<T>类型,它们再次为您执行所有线程编组。

Finally, if you do need to update the UI with an unending sequence of data, the best option is to use Reactive Extensions and observe on a captured SynchronizationContext . 最后,如果您确实需要使用无休止的数据序列更新UI,最好的选择是使用Reactive Extensions并观察捕获的SynchronizationContext

These options are from most common to least common. 这些选项从最常见到最不常见。 I'd guesstimate that 90% of use cases are covered with just async / await , 99% covered with async / await + IProgress<T> , and 100% covered with Rx. 我猜测90%的用例仅包含async / await ,99%覆盖了async / await + IProgress<T> ,100%覆盖了Rx。 I have never run into a case where BeginInvoke is necessary. 我从来没有碰到需要BeginInvoke的情况。 Or even beneficial. 甚至是有益的。

If you need to marshal actions onto the UI thread, yes, BeginInvoke is still the correct approach. 如果您需要将操作封送到UI线程,是的, BeginInvoke 仍然是正确的方法。

If you are already on the UI thread, but don't want your operation to block you can use await / async . 如果您已经 UI线程上,但不希望您的操作被阻止,则可以使用await / async Do note that this can still block your UI thread if the work being done isn't actually asynchronous and you are just wrapping it in a Task.Run . 请注意,如果正在完成的工作实际上并不是异步的,并且您只是将它包装在Task.Run ,这仍然会阻止您的UI线程。

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

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