C# ObservableCollection 和线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2293246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:09:45  来源:igfitidea点击:

ObservableCollection and threading

c#wpfmultithreadingobservablecollection

提问by ErikTJ

I have an ObservableCollectionin my class. And further into my class I have a thread. From this thread I would like to add to my ObservableCollection. But I can't do this:

ObservableCollection我班上有一个。进一步进入我的班级,我有一个线程。从这个线程我想添加到我的ObservableCollection. 但我不能这样做:

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

这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。

Note that this is not happening from the UI thread, so i don't have access to the dispatcher.

请注意,这不是从 UI 线程发生的,所以我无权访问调度程序。

采纳答案by Szymon Rozga

JaredPar's approach is a valid one. Another approach which is worth considering is using a thread safe ObservableCollectioninstead of the built-in ObservableCollection. There's a few implementations out there, but Sasha Barber's implementationand the CLinq Continuous Collection classare some of the better ones in my opinion. Internally, these classes essentially use the approach outlined by JaredPar, but encapsulate it inside the collection class.

JaredPar 的方法是一种有效的方法。另一种值得考虑的方法是使用线程安全ObservableCollection而不是内置的ObservableCollection. 有一些实现,但Sasha Barber 的实现CLinq Continuous Collection 类在我看来是一些更好的实现。在内部,这些类本质上使用 JaredPar 概述的方法,但将其封装在集合类中。

回答by JaredPar

The best way to solve this is to pass the Dispatcherobject to the start method of the background thread.

解决这个问题的最好方法是将Dispatcher对象传递给后台线程的 start 方法。

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var dispatcher = Dispatcher.CurrentDispatcher;
  ThreadStart start = () => BackgroundStart(dispatcher, col);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(
    Dispatcher dispatcher, 
    ObservableCollection<SomeType> col) {
  ...
  SomeType t = GetSomeTypeObject();
  Action del = () => col.Add(t);
  dispatcher.Invoke(del);
}

Now later on when you need to add to the collection you can use the UI Dispatcherobject.

现在,当您需要添加到集合中时,您可以使用 UIDispatcher对象。

As @Reed pointed out, a more general solution is achieved by using SynchronizationContext. Here's a functional style sample using SynchronizationContextto create a delegate responsible for adding new values. This has the advantage of hiding both the collection and the threading model from the code creating the object.

正如@Reed 指出的那样,使用SynchronizationContext. 这是一个功能样式示例,SynchronizationContext用于创建负责添加新值的委托。这具有在创建对象的代码中隐藏集合和线程模型的优点。

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var context = SynchronizationContext.Current;
  Action<SomeType> addFunc = (SomeType st) => context.Send(() => col.Add(st), null);
  ThreadStart start = () => BackgroundStart(addFunc);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(Action<SomeType> addFunc) {
  ...
  SomeType t = GetSomeTypeObject();
  addFunc(t);
}

回答by Cornel Marian

In.Net 4.5, you can use the Thread-safe collections, ConcurrentDictionary, ConcurrentBag etc, whichever suits your needs : http://msdn.microsoft.com/en-us/library/dd997305.aspx

在.Net 4.5 中,您可以使用适合您需要的线程安全集合、ConcurrentDictionary、ConcurrentBag 等:http: //msdn.microsoft.com/en-us/library/dd997305.aspx

Please consider reading also : http://www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So

请考虑阅读:http: //www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So