异步添加到ObservableCollection(或替代)

oli*_*i.G 9 .net c# data-binding wpf observablecollection

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

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

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

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

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

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

Roh*_*ats 15

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

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

App.Current.Dispatcher.BeginInvoke((Action)delegate()
                          {
                              observableCollection.Add(instanceOfYourClass);
                          });
Run Code Online (Sandbox Code Playgroud)

什么调度员要做的就是把它相关的线程上运行.因此,该项将始终添加到UI线程上,但可以在后台线程中创建.

这里有可能让你去这几个环节- 从BW更新和其他一个在这里


And*_*eas 7

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

 object lockObj = new object();
        BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj);
Run Code Online (Sandbox Code Playgroud)