My last post reguarding “Deadlocks and other issues with Invoke / BeginInvoke” was something of a rant on the subject of WinForms and multi-threading. I thought I’d post on the useage of the solution that was presented originally on the stackoverflow article. The following defines the interface portion of the class:

    public class EventHandlerForControl<TEventArgs> where TEventArgs : EventArgs
    {
        public EventHandlerForControl(Control control, EventHandler<TEventArgs> handler);
        public EventHandlerForControl(Control control, Delegate handler);

        public void EventHandler(object sender, TEventArgs args);
    }

Using this class is incredibly easy. Let’s assume our form is creating a ‘worker’ object and wants to know when some value has changes via an event. We simply need to modify the subscription to the event.

The wrong way:

    class MyForm : Form
    {
        public MyForm()
        {
            _worker = new Worker();
            _worker.OnUpdate += this.Worker_OnUpdate;
        }
        private void Worker_OnUpdate(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
                this.Invoke(new EventHandler(Worker_OnUpdate), sender, e);
            else
                ;//whatever
        }
    }

Now we just do the following with the help of EventHandlerForControl:

The right way:

    class MyForm : Form
    {
        public MyForm()
        {
            _worker = new Worker();
            _worker.OnUpdate += new EventHandlerForControl<eventargs>(this, this.Worker_OnUpdate).EventHandler;
        }
        private void Worker_OnUpdate(object sender, EventArgs e)
        {
            ;//whatever
        }
    }

Now whenever the event OnUpdate is fired it is automatically marshaled to the correct thread no special handling is needed. You can also be certain that either the call is successfully made or an exception will be thrown to the caller.

EventHandlerForActiveControl<T> – Use this class if you do not want an exception thrown when when the target control is not available. The method will not be called when the control is not active.

ForcedEventHandlerForControl<T> – Use this class if you do not want an exception thrown when when the target control is not available and you still want the method to execute.

All of these are defined here if you just want the source code.

Comments