Welcome to part 1 of the Powerful Extension Methods series. The extension method concept is an excellent feature of the latest breeds of the .NET framework. They allow us to abstract away static utility classes in a way that makes the utility methods appear to belong to the object they operate upon. Beginners can check things out here and here for a good introduction.
I do WinForms programming from time to time. In any Windows application, whether through traditional WinForms or through WPF, managing event handling in the face of threading is critical. Exceptions are thrown when code updates any UI Control property from any thread except the thread that created the control. This problem surfaces when some background thread needs to update the UI.
This led to a lot of creative solutions involving InvokeRequired and Invoke. One solution involves creating an event on the threaded object which the UI can subscribe to. The OnMyEvent method of the object handles invoking each event handler methods on the thread from which they subscribed. The full idea is described here.
It only took me an event handler or two before the DRY principle screamed for attention. Enter, the SafeInvoke extension method:
/// <summary>
/// Raises the event asynchronously.
/// </summary>
/// <param name="handler">The handler.</param>
/// <param name="source">The source.</param>
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
public static void SafeInvoke(this EventHandler handler, object source, EventArgs args)
{
if (handler != null)
{
foreach (EventHandler singleCast in handler.GetInvocationList())
{
var syncInvoke = singleCast.Target as ISynchronizeInvoke;
try
{
if (syncInvoke != null && syncInvoke.InvokeRequired)
{
syncInvoke.Invoke(singleCast, new object[] { source, args });
}
else
{
singleCast(source, args);
}
}
catch
{
// Do nothing. The event handler may have been detached asynchronously.
}
}
}
}
With this extension method, we can construct our threaded object to look something like this:
public class MyWorker
{
public event EventHandler SomeEvent;
protected virtual void OnSomeEvent(EventArgs e)
{
this.SomeEvent.SafeInvoke(this, e);
}
}
You can see that using this pattern, the event will manage on its own the process of ensuring the event is handled on the subscribing threads. No more threading exceptions when updating the UI from a background worker!
Another common event delegate that deserves a similar extension method is the generic EventHandler<T> class. The model of the function is no surprise; but, here it is in full.
/// <summary>
/// Raises the event asynchronously.
/// </summary>
/// <typeparam name="T">The type of the event handler arguments</typeparam>
/// <param name="handler">The handler.</param>
/// <param name="source">The source.</param>
/// <param name="args">The arguments containing the event data.</param>
public static void SafeInvoke<T>(this EventHandler<T> handler, object source, T args)
where T : EventArgs
{
if (handler != null)
{
foreach (EventHandler<T> singleCast in handler.GetInvocationList())
{
var syncInvoke = singleCast.Target as ISynchronizeInvoke;
try
{
if (syncInvoke != null && syncInvoke.InvokeRequired)
{
syncInvoke.Invoke(singleCast, new object[] { source, args });
}
else
{
singleCast(source, args);
}
}
catch
{
// Do nothing. The event handler may have been detached asynchronously.
}
}
}
}
Happy Coding!