【问题标题】:async Task.Run with MVVM异步任务。使用 MVVM 运行
【发布时间】:2014-12-09 20:46:23
【问题描述】:

我一直在玩新的异步 CTP 和 MVVM 模式。我一直在转换我的一个旧程序,该程序使用后台工作程序并报告进度以更新我的模型中的集合。我已将其转换为类似的东西

TaskEx.Run(async () =>
{
  while (true)
  {
    // update ObservableCollection here
  }
  await TaskEx.Delay(500);
});

在我看来,我绑定到我的视图模型,它公开了这个可观察的集合。但是,当我的收藏更新时,我得到以下异常

这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。

我不确定当这样完成时,拉回 UI 线程的正确方法是什么。

【问题讨论】:

  • 附带说明,您可以下载 Visual Studio 11 开发人员预览版中的 async 更新版本。

标签: c# mvvm asynchronous async-ctp


【解决方案1】:

您不必使用Task.Run() 或任何其他特殊方式运行异步方法,只需调用它们即可。在你的情况下,这正是导致问题的原因。

给定这样的函数:

Action f = async () =>
{
    while (true)
    {
        // modify the observable collection here
        await Task.Delay(500);
    }
};

从 UI 线程上运行的某个方法调用它,例如事件处理程序:

f();

完全按照它应该的方式工作。它执行循环的第一次迭代,然后返回。下一次迭代在 UI 线程上 500 毫秒(或更长,如果 UI 线程忙)后执行。

另一方面,如果你这样称呼它:

Task.Run(addNames);

它不能正常工作。这样做的原因是async 方法尝试在与它们启动时相同的上下文中继续(除非您另有明确指定)。第一个版本是在 UI 线程上启动的,所以它在 UI 线程上继续。第二个版本从 ThreadPool 线程开始(感谢Task.Run())并继续在那里。这就是它导致您的错误的原因。

所有这些都是使用SynchronizationContext 完成的,如果有的话。

【讨论】:

    【解决方案2】:

    您在主 UI 线程上创建了一个 ObservableCollection,并试图在异步后台线程上更新它,而这在 WPF 中是无法做到的。

    或者,从后台线程获取结果,然后将它们添加到主 UI 线程上的 ObservableCollection

    通常我在后台线程上更新 ObservableCollection 的代码如下所示:

    private async void LoadItems()
    {
        Task<List<MyItem>> getItemsTask = Task.Factory.StartNew(GetItems);
    
        foreach(MyItem item in await getItemsTask)
            MyCollection.Add(item);
    }
    
    private List<MyItem> GetItems()
    {
        // Make database call to get items
    }
    

    【讨论】:

      【解决方案3】:

      虽然您确实无法从第二个线程更新ObservableCollection,但可以创建异步可观察集合。这允许您从任务内或在未创建集合的线程上更新集合。

      我会发布示例,但我在这里找到了信息。它非常漂亮,我发现它是一个非常有用的例子。

      http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

      【讨论】:

        猜你喜欢
        • 2010-10-25
        • 2018-09-12
        • 2013-01-23
        • 2023-01-10
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多