BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 2.0+

The Generic EventHandler Delegate

In .NET 1.1, creating a custom event with event arguments often included the declaration of a new delegate. In .NET 2.0 and with the introduction of generics, the process is simplified with the standard EventHandler<T> delegate.

EventHandler Delegate

In a previous article I described the EventHandler delegate. This is a delegate provided by the .NET framework to simplify the creation of custom events. By using EventHandler you remove the requirement to create your own delegate to support your new event. The EventHandler delegate defines two parameters, which match the standard event pattern.

The first parameter is an object and is designed to hold the instance that raised the event. The second argument is an EventArgs object. As the EventArgs class doesn't support adding values, events based upon the delegate either include no additional event data, or the event arguments passed when the event is raised must be cast to a subclass in order to read the extra information.

EventHandler<T> Delegate

With the introduction of the .NET framework version 2.0, Microsoft added support for generics. This allowed the inclusion of a generic version of the EventHandler delegate, named EventHandler<T>. The generic delegate is similar to the non-generic version. It defines two parameters. The first is the sender object and the second the event arguments.

The key difference with EventHandler<T> is that the type for the event arguments parameter matches that of the generic type parameter for the delegate. So, if you wish to pass an event arguments type named, "ProgressEventArgs", you would create the event with the delegate EventHandler<ProgressEventArgs>. This means that, if you follow the standard event pattern, you should never need to create your own event handler delegates.

Example Event

To demonstrate the generic delegate we'll create a simple class with a method that simulates a long-running process. The method will report its progress via an event. To make the method take several seconds to execute we'll call the static Sleep method from the Thread class, so add the following using directive:

using System.Threading;

The code for the sample class is shown below. The DoSomething method loops from zero to one hundred with each iteration paused for one tenth of a second. After each pause the progress is reported using the OnProgressUpdated method.

OnProgressUpdated checks that the ProgressUpdated event has subscribers before raising it. The progress percentage value is set in the event arguments object's constructor. We'll see the code for the ProgressEventArgs class shortly.

Note the declaration for the ProgressUpdated event. We haven't used a custom delegate, instead applying the EventHandler<T> delegate with the type parameter set to ProgressEventArgs.

public class Processor
{
    public void DoSomething()
    {
        for (int i = 0; i <= 100; i++)
        {
            Thread.Sleep(100);
            OnProgressUpdated(i);
        }
    }

    private void OnProgressUpdated(int percentage)
    {
        if (ProgressUpdated != null)
        {
            ProgressUpdated(this, new ProgressEventArgs(percentage));
        }
    }

    public EventHandler<ProgressEventArgs> ProgressUpdated;
}

ProgressEventArgs is a simple subclass of EventArgs. It adds the ProgressPercentage property to hold the percentage of an operation that is complete. The property is set in the constructor.

public class ProgressEventArgs : EventArgs
{
    public ProgressEventArgs(int percentage)
    {
        ProgressPercentage = percentage;
    }

    public int ProgressPercentage { get; set; }
}

NB: A similar class exists in the System.Management namespace. For our example a custom class is useful. For real projects you should use built-in classes unless you are adding functionality.

Testing the Event

We can now create some code that runs the DoSomething method and outputs the information provided by the event. Update the Program class to include the following methods and run the program to see the results. You should see a percentage value that starts at zero and slowly rises to 100%.

static void Main(string[] args)
{
    Processor processor = new Processor();
    processor.ProgressUpdated += new EventHandler<ProgressEventArgs>(ShowProgress);
    processor.DoSomething();
}

private static void ShowProgress(object sender, ProgressEventArgs e)
{
    Console.WriteLine("{0}%", e.ProgressPercentage);
    Console.CursorTop--;
}
21 February 2013