Interthread Communication with C# in the .NET Framework

Okay, maybe I’m the lonely idiot who didn’t got this from the common instructions. If not, I hope that this article will help others to understand it more readily.

Abstract

In this article I explain how a resource intensive job is sourced out to its own thread. Furthermore I will discuss how to stay in communication with that thread. The article is for a Windows Forms application using C# in the .NET framework.

I will not talk about the theoretical concept of threading or event handling. It is assumed that you either know this or know where to learn about. (Or don’t know and even don’t want to know but simply make your application run.)

A source file is provided that contains a class with some templates for easy interthread communication.

Multithreading

In many applications one would like to carry out a computation in the background. I.e. the user interface shouldn’t “freeze” while the computation is running. Assume for example, a user started the evaluation by accident. He won’t be very pleased having to wait several minutes (or even longer) until he can correct his mistake.

The solution is to run the computation in its own thread. This is really easy:

private void button_Click(object sender, EventArgs e)
{
    private Thread kernel_thread;
    kernel_thread = new Thread(compute);
    kernel_thread.Start();
}
 
private void compute()
{
    // Here a complex job is carried out.
}

In this example, the method compute() will run in its own thread named kernel_thread. Note that compute() must be void and mustn’t take any arguments. Don’t forget to add

using System.Threading;

at the Begin of the code. If the user wants to abort the computation, the following would be a rough but effective way to do so:

private void kill_kernel()
{
    if (kernel_thread != null)
    {
        kernel_thread.Abort();
    }
}

I think there are better ways to achieve this since any intermediate results will probably be lost. However, for the case I had to solve this was an appropriate choice.

Event Handling

Everything is cute and dandy but yet the user doesn’t know what the “kernel” is doing. In fact, we would like to be able to communicate with it. Communication is a vast field but the very least we would like to do is enabling the kernel to print some status information. Writing a console application one could simply use

print("I'll be finished soon!");

replacing print by whatever command is appropriate for the chosen language.

For my Windows Forms application I have created a form with a text box that will accept the kernel output. Therefore the class has a method

public void log_print(string text)
{
    text_box.AppendText(text);
    text_box.AppendText(Environment.NewLine);
}

that takes a string and adds it to the text box. But this method can’t be called from the kernel. Event handlers are the solution of choice. As announced, I won’t explain the concept of event handling but simply give the solution.

Let’s go to the class that wants to write something to the text box. We want to have something like a notify(<some text>) method. Do get it, we first have to declare a delegate that will be invoked at the event. This handler must be void and take an object and an instance of the EventArgs class as argument. However, if we want to have it more customized, we can declare our own class that is derived from the EventArgs class. In our case, we want to send a string so we define

public class EventArgsNotification : EventArgs
{
    public string info_text; // The text we want to send.
}

Now we can declare our delegate

public delegate void EventHandlerNotification(object sender, EventArgsNotification e);

and an event

public static event EventHandlerNotification EventNotification;

Now we could fire this event using

EventArgsNotification e = new EventArgsNotification();
e.info_text = message;
EventNotification(this, e);

But not only that this are three lines of code for what we wanted to have a simple function it, even worse, also makes our application crash! The first problem can be solved by defining a method that does the job of declaring the event arguments an firing the event. The second problem is because the event is fired but nobody cares about. We should check this before we fire it. Here is the handy method:

private void notify(string message)
{
    if (EventNotification != null)
    {
        EventArgsNotification e = new EventArgsNotification();
        e.info_text = message;
        EventNotification(this, e);
    }
}

Subscribing to the Event

Now we have defined an event and can use it. But if it is fired, no one cares. In fact, it isn’t even fired because we check it for not being null. An event is something like a list of functions subscribing to it. So next we have to go to our class that contains the text box and add the following:

// Method that should be called if an event is fired:
private void receive_notification(object sender, EventArgsNotification e)
{
    log_print(e.info_text);
}
 
// Subscribe:
kernel.EventNotification += receive_notification;

Now we’ve subscribed a method to the event that will be called as it is fired. Whops, that doesn’t work! This is because as the method is subscribed to the event in the kernel class, it is also called from the thread the kernel runs on. This is not the thread the text box is managed on. Fortunately, the .NET framework provides us a good workaround. We rewrite the receive_notification method as follows:

private void receive_notification(object sender, EventArgsNotification e)
{
    if (InvokeRequired)
    {
        Invoke(new EventHandlerNotification(receive_notification), new object[] { sender, e });
    }
    else
    {
        log_print(e.info_text);
    }
}

InvokeRequired is true if the event is fired from a different thread. In this case, the above method will simply fire the event again from it’s own thread. (That’s what Invoke does.) This tools are provided in the ComponentModel so we add at the beginning

using System.ComponentModel;

That’s it!

Making Everything more Comfortable

Maybe we have a lot of classes that want to be able to notify the user. Doing all the stuff in each of them is a tedious exercise. I have written a little static class that allows to use fire a notification event from any class (on any thread) using

communication.FireNotification(this, <text here…>);

The definition of the EventArgsNotification class is also included in this file. It is static so an instantiation is not necessary. To subscribe to the event the same code as above is sufficient. Please don’t forget to correct the namespace to the one of your project.

Download communication class

Happy Coding!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s