Eri*_*kTJ 29 c# wpf multithreading observablecollection
ObservableCollection我班上有一个.进一步进入我的课程,我有一个主题.从这个线程我想添加到我的ObservableCollection.但我不能这样做:
这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection.
请注意,这不是从UI线程发生的,因此我无权访问调度程序.
Jar*_*Par 15
解决此问题的最佳方法是将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);
}
Run Code Online (Sandbox Code Playgroud)
现在,稍后当您需要添加到集合时,您可以使用UI Dispatcher对象.
正如@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);
}
Run Code Online (Sandbox Code Playgroud)
Szy*_*zga 15
JaredPar的方法是有效的.另一种值得考虑的方法是使用线程安全ObservableCollection而不是内置ObservableCollection.那里有一些实现,但在我看来,Sasha Barber的实现和CLinq Continuous Collection类是一些更好的实现.在内部,这些类基本上使用JaredPar概述的方法,但将其封装在集合类中.
在In.Net 4.5中,您可以使用Thread-safe集合,ConcurrentDictionary,ConcurrentBag等,以满足您的需求:http://msdn.microsoft.com/en-us/library/dd997305.aspx
请考虑阅读:http://www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So