HOME
  1. 1 Welcome
  2. 2 Overview
  3. 3 Start thread
  4. 4 Pass arguments
  5. 5 Call method on other class
  6. 6 More thread methods

Multi-threading in C#


This tutorial will take you through the basics of how to work with threads in C#. The concept is very similar to that of Java-threads.


Multi-threading overview


The threading functionality exists in the namespace System.Threading

This namespace provides classes and interfaces which enable multithreaded programming, i.e. parallel execution of code, and leveraging threads.

Example usage

  • Separate heavy calculations from UI (to avoid freezes)
  • Regularly query external service, and notify application if new data arrived (polling)
  • To avoid stopping processing when waiting for user's input
  • When you have independent tasks, which do not intersect
  • Handling multiple clients in a client-server setup with sockets

Starting a thread, and printing numbers


In Java the Thread constructor takes an instance of a class, which implements the interface Runnable.
In C# the Thread constructor takes a delegate, i.e. either a lambda expression, or a method reference.

As an example, we would like to execute the following method in a new thread:

public void PrintNumbers()
{
    for (int i = 0; i < 1000; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(100);
    }
}

This method just prints out numbers from 0 to 999. Notice the Thread.Sleep(100) method call, which sleeps the current thread for 100 milliseconds. Identical to the sleep() method in Java.

Now, we would like to create a thread to execute this method in a new thread. That can be done as follows:

Thread thread = new Thread(PrintNumbers);
thread.Start();

A new thread instance is created, the constructor takes a method reference to the PrintNumbers method shown above.
When the Start() method is called on the thread a new thread is created, and the method is executed.


Passing arguments


In the previous example, we just referenced a method. This can be done, when we don't need to pass any arguments.

The below method also prints numbers, but requires an argument.

public void PrintNumbers(int count)
{
    for (int i = 0; i < count; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(100);
    }
}

The way we start the thread now is to use a lambda expression, like below:

Thread thread = new Thread( () => PrintNumbers(1000) );
thread.Start();

This lambda expression is an anonymous method.
() => PrintNumbers(1000)
The leading () defines the arguments to be passed to the method. In this case, there are none, so the parameter list is empty. The => is the lambda operator, so the right hand side is the functionality to execute, in this case it's a method call to PrintNumbers.


Calling a method on another class


Sometimes we would like to keep the behaviour in a separate class. E.g. in Java we usually create a separate class, which implements the Runnable interface, and so the run() is called, when the thread is started. We can do something similar in C#.

Below is a class, which has a method to print numbers, like previous examples.

public class NumberPrinterClass
{
    public void PrintNumbers(int count)
    {
        for (int i = 0; i < count; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(100);
        }
    }
}

Now, we would like to execute this functionality in a thread, created from a different class.
In the below main method, a new instance of the above class is created, and then a thread, which is started.

static void Main(string[] args)
{
    NumberPrinterClass npc = new();
    Thread thread = new Thread(() => npc.PrintNumbers(100));
    thread.Start();
}

More thread methods


Similar to Java, we have a couple of methods available for the threads. Relevant methods are:

  • Thread.sleep(milliseconds : long)
  • thread.Join(otherThread) - to tell a thread to not start until the argument thread object is finished. This will make the threads run in serial.
  • thread.Interrupt() - to wake up a sleeping thread. It throws an exception, which must be handled.