Monday, August 27, 2012

WPF Multithreading & ICollectionChanged

WPF Multithreading & ICollectionChanged

I'm currently using .NET 3.5 for a project and I need to implement a static Queue that gets it's items enqueued by one background thread and dequeued by yet another. Since there isn't an ObservableQueue or something similar in .NET 3.5 I tried to derive my own Queue and implement INotifyCollectionChanged, since my UI should display the contents of the Queue to the user.

But when I try to run it, the first background worker enqueues an item, CollectionChanged gets raised and then I end up with an exception like

c# the calling thread cannot access this object because a different thread owns it

My business objects (those things in the queue) all implement INotifyPropertyChanged and the background worker that dequeues them also changes some properties and therefore the same thread also calls PropertyChanged along with CollectionChanged. Strangely enough I don't got any error when PropertyChanged get raised, but CollectionChanged crashes... can someone help me on this?

Answers & Comments...

Answer: 1

Have you tried to delegate when your background thread modifies the queue ?

Like :

if (Dispatcher.Thread != Thread.CurrentThread) {        Dispatcher.Invoke(new Action(delegate()        {            //Modify your collection        }));  } 
by : chrisendymionhttp://stackoverflow.com/users/1465458

Answer: 2

You get such an exception when you're trying to interact with GUI from non-dispatcher (i.e. non-GUI) thread. In your case I assume you're just raising CollectionChanged event without checking whether it is GUI-thread or not. In order to resolve this issue you should, as chrisendymion wrote, us Dispatcher. I see two possible options here:

1) Every call to your custom queue (add/delete) is made on Dispatcher (Dispatcher.Invoke)

2) Wrap code that raises CollectionChanged event to the same Dispatcher.Invoke.

Hope this helps.

by : Alexanderhttp://stackoverflow.com/users/1395582

Answer: 3

Use something like this:

if (System.Windows.Application.Current.Dispatcher.CheckAccess())         {             Messages.Add(message);         }         else         {             System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,                 new Action(() => Messages.Add(message)));         } 

You can only access the from GUI-Thread because it is possible that the GUI is bound to the collection. And a lot of threads working with the gui isnt that good thing because as result you will often recieve errors.

So just think about: Why do you can't do something like this: listBox1.Items.Add(...) from another thread. Now you know why you can t do access the list from another thread.

(if you really don t know why you can do something like listBox1.Items.Add(...) google for it... you will find a lot of articles

by : thefiloehttp://stackoverflow.com/users/1293906




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog