后台操作阻止ObservableCollection绑定后的UI更新

时间:2011-11-22 17:58:07

标签: wpf observablecollection

我有这个:

  1. 显示等待动画,以便在后台执行加载操作时“阻止”用户界面。
  2. 在加载结束时,我调用一个实例用户控件并使用Bindings显示一些数据的方法(以及其他的ObservableCollection)
  3. 此用户控件显示,用户可以与之交互,但ObservableCollection似乎卡在另一个线程中,因为它不允许向其添加新项目。
  4. 我尝试在BackgroundWorker的Completed事件中更新UI,使用Dispatcher,使用DispatchTimer ...所有这些都显示用户控件,但ObservableCollection仍无法用于添加。

    尝试将项添加到集合的代码位于UserControl内。

    确切的错误是:“这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection

    如果我不在后台加载,就不会发生这种情况。

    感谢您为此提供的任何解决方法。

    顺便说一句,尝试使用Dispatcher添加项目也不起作用。

    换句话说,我想做的是在后台处理UI线程中创建一个对象......我知道这可能听起来很傻。

5 个答案:

答案 0 :(得分:1)

您可能需要查看您使用的是哪个Dispatcher?在您的情况下,您可能指的是两个不同的调度员。

为什么不使用thread safe observable collection

答案 1 :(得分:1)

通常我会在我的UI线程上创建对象,然后用从后台线程获得的数据填充它们。

例如,

void async LoadButton_Clicked(object sender, EventArgs e)
{
    MyCollection = new ObservableCollection<SomeItem>();

    // Can also use a BackgroundWorker
    var collectionData = await GetCollectionData();

    foreach(var item in collectionData)
    {
        MyCollection.Add(item);
    }
}

我正在使用C#5.0 asyncawait关键字进行异步操作,但您也可以使用BackgroundWorker来完成后台工作。

您还可以使用Dispatcher.BeginInvoke()进行更轻松的后台工作(例如将数据复制到MyCollection),但是对于繁重的工作,我发现它仍然会锁定UI,因此我更喜欢使用后台线程。

答案 2 :(得分:0)

如果视图绑定到此集合,则无法在单独的线程上修改ObservableCollection的内容,而是可以覆盖ObservableCollection并为其提供支持并在整个应用程序中使用它。

此示例包含您想要的内容 - http://tomlev2.wordpress.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

答案 3 :(得分:0)

当谈到线程和ui元素时,最重要的遵循的规则之一可能会让你在长期运行中遇到很多麻烦,就是在ui-thread上保持ui-element实例化。当然你可以管理它。如果您需要从另一个线程更改这些对象,您可以使用Dispatcher。

threading model引用也可能有意义)

答案 4 :(得分:0)

谢谢大家的帮助......一位来自MS的人访问了公司(对于商业注释感到抱歉)做其他事情,我把他收起来并展示了这种行为。在2分钟内找到了问题的根源......我不太确定。

碰巧我正在使用ICollectionView来显示我有问题的ObservableCollection的排序/过滤版本。我在我的类的构造函数中创建了这个ICollectionView,所以在反序列化时它是在另一个线程中创建的。他建议在代码中将此创建移动到更长的时间(当相关属性被读取时)。这解决了这个问题。

然而,在其他线程中创建的ObservableCollection现在允许我添加新项目。不知道为什么,但现在它有效。

很抱歉这么晚,再次感谢你。