2013-09-09 5 views
2

Это мой подход для добавления элементов в ObservableCollection в отдельный поток, взятый из ThreadPool.ObservableCollection, заполненный нитью ThreadPool

Как мы знаем, что это поднимет исключение:

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; 

     } 
    } 
} 

Какое решение лучше всего подходит для решения этой проблемы?

Спасибо!

+0

Либо используйте WPF 4.5, где разрешена такая деятельность по перекрестным потокам, либо - еще лучше - подготовьте данные в фоновом потоке, верните его, а затем заселите наблюдаемую коллекцию в потоке пользовательского интерфейса ... –

ответ

3

Заменить

container.internalList.Add(item); 

по

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

Таким образом Add выполняется на Dispatcher потоке.

1

Вы можете просто получить данные из фонового потока в качестве List, а затем бросили этот список к ObservableCollection следующему

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

Я надеюсь, что это помогает.

1

Убедитесь, что вы устанавливаете свойства UI объектов в потоке пользовательского интерфейса:

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

Это добавит код в фигурных скобках на очереди рабочих элементов в потоке пользовательского интерфейса Dispatcher.

1

Проблема не в коллекции на вашем классе, а в элементе управления, который является обязательным для этой коллекции из потока пользовательского интерфейса.

Существует что-то новое в 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