I have an ObservableCollection
in 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:
This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
Note that this is not happening from the UI thread, so i don't have access to the dispatcher.
The best way to solve this is to pass the Dispatcher
object to the start method of the background thread.
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 Dispatcher
object.
As @Reed pointed out, a more general solution is achieved by using SynchronizationContext
. Here's a functional style sample using SynchronizationContext
to 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.
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);
}