在主线程上执行异步任务的最佳方式
Best way to execute asynchronous task on main thread
我想知道在 .NET 应用程序(准确地说是在 ViewModel 中)的主线程上执行任务的最佳异步方式是什么。 Dispatcher.BeginInvoke 现在仍然有效还是存在更好的方法?
如果您需要将操作编组到 UI 线程,是的,BeginInvoke
仍然 是正确的方法。
如果您已经在 UI 线程上,但不希望您的操作被阻塞,您可以使用await
/async
.请注意,如果正在完成的工作实际上不是异步的并且您只是将其包装在 Task.Run
.
BeginInvoke
很低级;总有更好的方法可用。
在大多数情况下,您可以使用 async
/await
从 UI 线程启动异步操作,并自动 return 到 UI线程显示结果。默认情况下,UI 上下文由 await
捕获,并用于在等待的操作完成后恢复 async
方法。 (我更详细地描述了这一点on my blog)。
如果您需要显示来自 UI 的进度报告,最好的选择是 IProgress<T>
/Progress<T>
类型,它再次为您进行所有线程编组。
最后,如果您确实需要使用无休止的数据序列更新 UI,最好的选择是使用 Reactive Extensions 并观察捕获的 SynchronizationContext
.
这些选项从最常见到最不常见。我估计 90% 的用例仅包含 async
/await
,99% 包含 async
/await
+ IProgress<T>
,以及 100 % 被 Rx 覆盖。我从来没有 运行 遇到需要 BeginInvoke
的情况。甚至有益。
我想知道在 .NET 应用程序(准确地说是在 ViewModel 中)的主线程上执行任务的最佳异步方式是什么。 Dispatcher.BeginInvoke 现在仍然有效还是存在更好的方法?
如果您需要将操作编组到 UI 线程,是的,BeginInvoke
仍然 是正确的方法。
如果您已经在 UI 线程上,但不希望您的操作被阻塞,您可以使用await
/async
.请注意,如果正在完成的工作实际上不是异步的并且您只是将其包装在 Task.Run
.
BeginInvoke
很低级;总有更好的方法可用。
在大多数情况下,您可以使用 async
/await
从 UI 线程启动异步操作,并自动 return 到 UI线程显示结果。默认情况下,UI 上下文由 await
捕获,并用于在等待的操作完成后恢复 async
方法。 (我更详细地描述了这一点on my blog)。
如果您需要显示来自 UI 的进度报告,最好的选择是 IProgress<T>
/Progress<T>
类型,它再次为您进行所有线程编组。
最后,如果您确实需要使用无休止的数据序列更新 UI,最好的选择是使用 Reactive Extensions 并观察捕获的 SynchronizationContext
.
这些选项从最常见到最不常见。我估计 90% 的用例仅包含 async
/await
,99% 包含 async
/await
+ IProgress<T>
,以及 100 % 被 Rx 覆盖。我从来没有 运行 遇到需要 BeginInvoke
的情况。甚至有益。