tags:

views:

112

answers:

1

I have the following bit of code that modifies an observable collection of 'screens' whenever a user leaves.

void OnUserLeft(int roomId, int userId, string username)
    {
        client.ClientDispatcher.Invoke(
            (Action<int>)((id) => 
            {
                Console.WriteLine("Hello before the storm!");
                var screensToCheck = client.Screens.Where(s => s.CpuId == id).ToList();
                screensToCheck.Each(s => client.Screens.Remove(s));
                Console.WriteLine("Hello there!");
            }), userId);
    }

This is wrapped in a call to the client's Dispatcher, supposedly to get past the threading issues related to CollectionViews. However, I still get the following exception:

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

The Dispatcher you see above is set in the WPF application's MainViewModel (we're using MVVM), like so:

public Dispatcher ClientDispatcher
{
    get { return Dispatcher.CurrentDispatcher; }
}
+2  A: 

From the documentation of CurrentDispatcher:

Gets the Dispatcher for the thread currently executing and creates a new Dispatcher if one is not already associated with the thread.

It looks like you are accessing CurrentDispatcher while not in your UI thread, and invoking your operation on it (i.e., the Invoke has no effect at all because the thread you are in does not have a Dispatcher; a new one is created on the spot and the call goes to it).

You should be saving the value of Dispatcher.CurrentDispatcher at the point where you create the Client instances (assuming you are doing that from within the UI thread), for example:

class Client {
    Client() {
        this.OwningDispatcher = Dispatcher.CurrentDispatcher;
    }

    Dispatcher OwningDispatcher { get; private set; }
}

If your Client instances are not created on the UI thread, you need some way of getting the correct value of Dispatcher over to them.

Jon
This is the first time we're actually trying to delete something, using the Dispatcher to do so. So you're saying that our Dispatcher probably wasn't implemented correctly in the first place? I'll try that out now.
Dusda
Success! You sir, are brilliant.
Dusda
I wouldn't call this the result of brilliance. I just read the documentation for the features the code uses carefully. :-)
Jon