How to raise and consume custom events in C#

When something happens asynchronously, the events mechanisms in C# is a good way for different components of our C# programs to notify one another about it.

For example, when the report generation component had the finance report ready, it can raise an event to components that had registered interest in that finance report.

This post documents how we can raise and consume custom events in C#.

Defining a delegate for components that are interested in the event

We first define the delegate that will hold C# methods from components which need to be notified when our report is completed by the report generation module.

Components which are interested in the report generation module shall provide a method that returns nothing and accepts a string as its only input parameter.

public delegate void ReportCompletedHandler(string report);

I tend to put the definition of the delegate in the same source file that defines the component which will fire the event.

Defining the event object

We then define the event object as an instance variable in the class definition of the component which will fire the event.

public event ReportCompletedHandler reportCompleted;

The event keyword defines the delegate that we had defined earlier as a custom event and makes the event available through the variable reportCompleted.

Registering interest in the event

To register interest in the event, we first define a method which had the same signature as the delegate, ReportCompletedHandler.

private void displayReport(string report) 
{
    Console.WriteLine("Received report: " + report);
}

And then add the method as a delegate to the event:

reportCompleted += new ReportCompletedHandler(this.displayReport);

Firing the event

When the report is ready, the report generation component will first check whether there are delegates registered to the reportCompleted event. If there are interested parties registered to the event, it will fire the event.


String report = "<A sample report>";

if (reportCompleted != null) 
{
    reportCompleted(report);
}

A complete example for this post

The delegate and event generator source

// Define delegate for components that are interested in report completion
public delegate void ReportCompletedHandler(string report);

// The event generator source
public class ReportGenerator
{
    public event ReportCompletedHandler reportCompleted;

    public void generateReport()
    {
        // Fire report completed event with report
        string report = "<A sample report>";

        if (reportCompleted != null)
        {
            reportCompleted(report);
        }
    }
}

A component that is interested in report completion

public class ReportDisplayer 
{

    public ReportDisplayer()
    {
        // Register interest in the completed report
        ReportGenerator.getInstance().reportCompleted += new ReportCompletedHandler(this.displayReport);
    }

    public void displayReport(string report)
    {
        Console.WriteLine("Diplaying report:");
        Console.WriteLine(report);
    }

}

Class that contains the main method to start the program

using System;
public class Program
{
    public static void Main(string[] args)
    {

        // Set up report displayer
        ReportDisplayer reportDisplayer = new ReportDisplayer();

        // Trigger report generation
        ReportGenerator.getInstance().generateReport();

    }
}

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.