Welcome to the first in a series of tutorials on Multi-Threading in C#. Before we even think about looking at any code, I think first, since this is the intro tutorial, we need to discuss what multi-threading is, and how it can benefit your application. We will also discuss some short falls in multi-threading capabilities.

What is multi-threading?

If you were to ask 100 programmers the question "What is a thread?", you'd leave with 100 different answers. To me a Thread is a tool that allows concurrent, independent processes to run parallel to one another, without affecting each other, and without having to wait for the other to complete before it can execute. It used to be that an application had but a single thread, which meant a process was made operate sequentially from beginning to end, with no variations. With the introduction of multi-threading you can run step 1 in its own thread, while running step 2 in a separate thread. While that may not always be a good idea, especially if step 1 requires results from step 3, so that was just an example of how multi-threading works.

Why multi-thread?

Multi-threading allows your application to run more efficiently, multi-threading affords you the opportunity to run resource intensive processes in the background, allowing your interface to remain usable. If you were to run your entire application in a single thread, you would notice at times that your user interface would, for all intents and purposes, be unusable, until the current process completed. Though there are numerous advantages to creating multi-threaded applications, there are also safety concerns. The main concern when creating multi-threaded applications is the possibility of multiple threads manipulating the same data, or space in memory, at the same time, this is known as a Race Condition.

Debugging a Race Condition can be difficult, as the condition can be sporadic and are often hid from the developer, and may not appear until the application is ran repeatedly. As long as you write thread-safe code you can avoid race conditions. Determining if code is thread-safe usually isnt an easy task, but there are several items that will reveal unsafe code, such as instantiating a class that contains static variables and indirectly accessing shared memory with the use of pointers or handles.

Limiting or avoiding the sharing of data across multiple threads is a way of ensuring you're code is thread-safe, but there are times when this is necessary. Say you have a large process running in the background, and you're wanting to keep the user updated on the progress of said process. Since the controls on the form are only accessible by the thread in which they were created, and sharing of data between threads is dangerous, for the lack of a better term, what do you do?

In this situation you would use a Delegate to marshal the call onto the thread that created the controls, using the Invoke Method. There are four methods that you can call from any thread and still have your code considered thread-safe:

Now that we have a better understand of what a thread is, and what multi-threading is, lets look at how we would go about using a Delegate to marshal a call onto the UI thread with the Invoke Method. First we, as usual, need references to our Namespaces. The Namespaces we will be using are:

using System;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Collections.ObjectModel;

Now we need our variables that will be referenced throughout our class. One of the variables is an ISynchronizeInvoke which allows us to synchronously or asynchronously execute our delegate. So here are the variables I use:

Next, we need a Delegate which we will use to marshal our call to the UI Thread, so we can display the progress of our process to the user on the UI:

//our delegate, which will be used to marshal our call
//to the UI thread for updating the UI
public delegate void ProcessStatus(string Message,int status);

Next, as with any class we need Constructors. A constructor is a member function with the same name as its class, and are used to create, and can initialize, objects of their class type. Constructors can be empty, the can accept no parameters and set variables to a desired state when the class is initialized, they can also accept parameters for initializing variables global to the class to a certain value:

Next, we get to the heart of our class, the methods that do our work. The first method will initialize our Thread. In this method we use the IsBackground Property of the thread to tell it to run in the background, then we name the thread and start it:

When you create a new Thread you need to pass it the name of the process that the thread will be executing. In this case we are passing it the AddItemsToList, which we use to add items to our Collection<string>. While we are adding to our collection, we also lock the collection so it cannot be accessed by any other threads, preventing a race condition:

Since this is merely an example we aren't really doing anything big here, we are simply looping from 0 to 100 adding the counter object's value to our list. We then, on each iteration through the loop, use Sleep Method of the Thread Class to make it appear to be a larger process than it really is. You will notice that right before the Sleep method there is a call to a method named UpdateStatus. UpdateStatus is the method we are using to send our message to the UI Thread.

Here we create an object array that holds 2 items. You will also notice the method requires 2 parameters, msg and status, these parameters will be used to populate our object array. We then use the Invoke Method of the ISynchronizeInvoke Interface:

Using this we can update any UI component in the main thread without worrying if the call is being made from the proper thread. So as you can see, there is a thread-safe way to share data between threads. Though we aren't using data, we're simply updating a component on the UI with the status of our background thread. This process can now rune while leaving the UI in a usable state.

That is the end of the tutorial on Cross Thread Communication in C#, I hope you found this tutorial useful and informative. As I stated before, this is just the first in a series on multi-threading in C#, and what is available in the System.Threading Namespace.

"serviceGUI()" is a GUI level method within the form (this) that can change as many controls as you want. Just call sendToGUI() from the other thread. Parameters can be added to pass values, or just use class scope variables.

Agree with the previous comment - a complete example would really help. If I knew what code went where, I wouldn't need the article!

Don't agree: If you don't understand where this code belongs, you don't understand the code. If so, you first need to understand the basic concepts of threading and should read another resource.

The example is (almost) complete. All the code listed goes in one class. The only thing missing is an example how to use that class, in particular what can be passed as a ISynchronizeInvoke. An example would be to use the form:

"serviceGUI()" is a GUI level method within the form (this) that can change as many controls as you want. Just call sendToGUI() from the other thread. Parameters can be added to pass values, or just use class scope variables.

This is perfect, that's what i've been looking for last few days. Everybody writes about delegates, an.pipes or named pipes. Here is a simple answer for my big problem. Thanks for telling me how invoke sth i the parent's context. Great!