Blog Home  Home Feed your aggregator (RSS 2.0)  
Eric Malamisura's Blog - Multithreading with Events
Geek Ramblings
 
 Monday, May 21, 2007
A typical problem that is encountered using multiple threads and events is that when you fire your event, the subscriber to that event will be running from the thread that initiated the event.  The typical way of getting around this is to check InvokeRequired in the windows form and then use Invoke of that form to Invoke the event.  Wouldn't it be nice if you could marshall that event to the proper thread before the UI gets the event?  I mean you wouldn't have to deal with it, it would just work.

So you may wonder why didn't the .NET team just build this into WinForms?  Well I wondered that to, but I watched a Channel 9 video (can't remember which one) where basically they said they didn't do this because it would put a huge performance burden if every single event had to be thread safe.  So in order to achieve optimal performance it was up the developer to only make a form/component/etc thread safe only when it needed to be thread safe.  This way performance is optimal.

With that said you can use the below code snippets that a co-worker of mine pulled from the Microsoft CAB Framework, you can use it to marshal an event to the control where the synchronization context is located.  All WinForms have a SynchronizationContext, which is used by the FireMarshalledEvent method to marshal the event to the forms thread context.

Below is a very simplified example of how this would work, I would suggest you modify it to your needs before using it:

void FireMarshalledEvent(SynchronizationContext syncContext, Delegate eventDelegate, EventArgs eventArgs)
{
    if (eventDelegate != null)
    {
        if (syncContext != null)
        {
            syncContext.Send(
                delegate(object data)
                {
                    try
                    {
                        ((Delegate)data).DynamicInvoke(this, eventArgs);
                    }
                    catch (TargetInvocationException exp)
                    {
                        //Log Error
                    }
                    }, eventDelegate);
                }
        else
        {
            eventDelegate.DynamicInvoke(this, eventArgs);
        }
    }
}

public event EventHandler<EventArgs> MyEvent;

FireMarshalledEvent(SynchronizationContext.Current, MyEvent, new EventArgs());


Monday, May 21, 2007 2:20:17 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]    | 
Copyright © 2009 Eric Malamisura. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.