由ThreadPool中的线程填充的ObservableCollection

时间:2013-09-09 10:53:59

标签: c# wpf multithreading

这是我在从ThreadPool获取的单独线程中向ObservableCollection添加项目的方法。

我们知道它会引发异常:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

我知道这个主题在这里很受欢迎,但我没有找到任何适合下面代码中描述的情况的解决方案:

namespace WpfApplication1
{
    class Item
    {
        public string name
        {
            get;
            set;
        }
    }

    class Container
    {
        public ObservableCollection<Item> internalList = new ObservableCollection<Item>();

    }

    public partial class MainWindow : Window
    {
        Container container = new Container();

        void addItems()
        {
            Item item = new Item() { name = "jack" };
            container.internalList.Add(item);

        }

        public MainWindow()
        {
            InitializeComponent();

            ThreadPool.QueueUserWorkItem(delegate { this.addItems(); });
            MyDataGrid.ItemsSource = container.internalList;

        }
    }
}

这个问题的最佳解决方案是什么?

谢谢!

4 个答案:

答案 0 :(得分:3)

替换

container.internalList.Add(item);

通过

Dispatcher.BeginInvoke(new Action(() => container.internalList.Add(item)));

这样AddDispatcher线程上执行。

答案 1 :(得分:1)

您可以将后台主题中的数据作为List,然后将此列表转换为ObservableCollection,如下所示

List<SomeViewModel> someViewModelList = await GetYourDataAsListAsync();
ObservableCollection<SomeViewModel> Resources = new TypedListObservableCollection<SomeViewModel>(someViewModelList);

我希望这会有所帮助。

答案 2 :(得分:1)

确保在UI线程上设置UI对象的属性:

Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate()
{
    MyDataGrid.ItemsSource = container.internalList;
});

这会将大括号内的代码添加到UI线程Dispatcher的工作项队列中。

答案 3 :(得分:1)

问题不在您的类的Collection中,而是在从UI Thread绑定到此集合的Control中。

WPF 4.5中有一些新功能: http://www.jonathanantoine.com/2011/09/24/wpf-4-5-part-7-accessing-collections-on-non-ui-threads/

//在某处创建锁定对象
private static object _lock = new object();

//启用其他地方对此集合的交叉访问 BindingOperations.EnableCollectionSynchronization(_persons, _lock);

MSDN: http://msdn.microsoft.com/en-us/library/hh198845(v=vs.110).aspx