Performing Cross-Thread calls using the SynchronizationContext class

If you ever performed concurrent operations in .net, you might have stumbled across the problems that occur when you try to set/access the properties of an Object that's at home in another thread (e.g. when you try to set a Control state from a data loading BackgroundWorker). A very convenient way of bypassing this is the use of Control.InvokeRequired() and Control.Invoke(), which utilizes a delegate to send a message to the Control's thread.
Anyway, this only works for Controls, and you might want just a little more than that.
If so, you should look into SynchronizationContexts. It does pretty much the same thing, but works on non-GUI objects as well.

The following sample is an approach you could use to keep track of all objects' SynchronizationContexts for being able to call DoSomething() on them later.
Please make sure you add Exception handling wherever appropriate.


public class StateToggler
{
private Dictionary<object, SynchronizationContext> synchronizationContexts =
new Dictionary<object, SynchronizationContext>();

public void RegisterObject(object obj)
{
this.synchronizationContexts.Add(obj, SynchronizationContext.Current);
}

public void DoSomethingToObject(object state)
{
if (!this.synchronizationContexts[state] == SynchronizationContext.Current)
{
this.synchronizationContexts[state].Send(DoSomethingToObject, state);
}
else
{
state.DoSomething();
}
}
}


Testing this in NUnit got me stuck though. The Debugger should enter DoSomethingToObject() after the first call of Send(), but it just plain doesn't.
I suppose NUnit's way of working (ThreadRunner) has some problems with this...

Kommentare

Beliebte Posts aus diesem Blog

Using AutoMapper for MVVM implementations

Deploying ClickOnce-applications in different environments without modifying the assembly identity

Preparing for and passing MCTS exam 70-536