【问题标题】:Best way to execute asynchronous task on main thread在主线程上执行异步任务的最佳方式
【发布时间】:2015-07-14 11:17:21
【问题描述】:

我想知道在 .NET 应用程序的主线程上执行任务的最佳异步方式是什么(准确地说是在 ViewModel 中)。 Dispatcher.BeginInvoke 现在仍然有效还是存在更好的方法来做到这一点?

【问题讨论】:

  • 我很确定你不想在视图模型中引入多线程,也许在使用 async ... await 结构的控制器中。
  • 好的。在 ViewModel 中做一些异步/等待有什么问题吗?
  • 视图模型中的线程(或异步等待)没有任何问题。
  • @garryp 从模型中加载数据怎么样?如果我的模型是 WCF 代理,也许它有可等待的方法(实际上有这个)。即使您将await 抽象为“一劳永逸”的方法,VM仍然有效地引入了线程。我认为您对所涉及的交互的看法有点简单,但我很容易错了:)。
  • 如果不涉及非常具体的示例,这很困难,但我认为模型不应该将这类信息暴露给相当高级别的视图模型。我猜你正在考虑一个非常聪明的模型,而我更喜欢那些非常愚蠢的模型,服务和助手封装了诸如对 WCF 服务的调用之类的东西。

标签: c# .net wpf asynchronous async-await


【解决方案1】:

如果您需要将操作编组到 UI 线程上,是的,BeginInvoke仍然正确的方法。

如果您已经 UI 线程,但不希望您的操作阻塞,您可以使用await/async。请注意,如果正在完成的工作实际上不是异步的,而您只是将其包装在 Task.Run 中,这可能仍然阻塞您的 UI 线程。

【讨论】:

    【解决方案2】:

    BeginInvoke 非常低级;总有更好的方法可用。

    在大多数情况下,您可以使用async/await 从 UI 线程启动异步操作,并自动返回 UI 线程显示结果。默认情况下,UI 上下文由await 捕获,并用于在等待的操作完成后恢复async 方法。 (我更详细地描述了这一点on my blog)。

    如果您需要从您的 UI 显示进度报告,最好的选择是 IProgress<T>/Progress<T> 类型,它再次为您执行所有线程编组。

    最后,如果您确实需要使用无休止的数据序列更新 UI,最好的选择是使用反应式扩展并观察捕获的 SynchronizationContext

    这些选项从最常见到最不常见。我估计 90% 的用例只被 async/await 覆盖,99% 被 async/await + IProgress<T> 覆盖,100% 被 Rx 覆盖。我从来没有遇到过需要BeginInvoke 的情况。甚至是有益的。

    【讨论】:

    • 很好的答案。谢谢!
    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多