异步添加到ObservableCollection(或替代)

这就是我所拥有的 – 一个ListBox,其ItemsSource设置为ObservableCollection – 其中T是我的自定义类,表示一个文件,只包含2个DependencyProperties:Filename和ThumbnailPath。 – 列表框还定义了自定义DataTemplate,以便在其下很好地显示图像和文件名。

列表框的目的是显示当前文件夹中的video文件(在TreeView中选择),缩略图(异步生成;不是此问题的一部分)。

因此,当我更改TreeView中的文件夹时,ObservableCollection将被清除并再次填充,这将自动反映在ListBox项目中。

问题在于:UI变得无法响应,更新需要几秒钟。 同样,缩略图在这里没有意义(我尝试禁用它们)。 我认为花费最多时间的是构建我自定义类的50-100个实例及其可视化表示 – 它必须为每个实例初始化一个Image对象。 但这只是我的猜测 – 你能否确认或排除这种可能性?

我开始认为ObservableCollection可能不是这里的方式 ,因为根据我的阅读和我尝试的内容,没有办法异步添加项目,至少如果这些项目是DependencyObjects。 我尝试使用BackgroundWorker创建我的类实例,并将它们添加到ProgressChanged事件处理程序中的集合中,但它会抛出exception(某些线程与dependencyobjects问题)。

有什么东西我不见了吗? 或者通过简单地抛弃ObservableCollection并编写一个好的旧异步for循环来添加项目,我会更好吗?

由于您的ObservableCollection绑定到UI,因此它在UI线程上生成,因此任何进一步的更新(删除/添加/清除)必须位于同一UI线程上。 它不允许来自另一个线程的更新。

但是,你可以做的是创建你的类的insance(或在后台线程上进行所有耗时的操作),完成后,使用你的UI线程的Dispatcher在ObservableCollection中添加对象,如下所示 –

 App.Current.Dispatcher.BeginInvoke((Action)delegate() { observableCollection.Add(instanceOfYourClass); }); 

Dispatcher所做的是将操作放在其关联的线程上。 因此,该项将始终添加到UI线程上,但可以在后台线程中创建。

这里有一些链接可能会让你去 – 从BW和其他一个更新

使用.net 4.5,您可以使用EnableCollectionSynchronization

  object lockObj = new object(); BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj);