C# Thread

By FoxLearn 12/9/2024 8:02:11 AM   114
In C#, a Thread is a unit of execution within a process. Each Thread represents a separate execution path, and multiple threads can run concurrently within the same application.

Threads are managed by the .NET runtime, and you can create and control threads using the System.Threading namespace.

C# Thread Start

// This is the method that will be executed in a separate thread.
static void Task()
{
    Console.WriteLine($"Thread Id: {Thread.CurrentThread.ManagedThreadId}");
}

In Main method.

// Print the main thread's ID
Console.WriteLine($"Main thread Id: {Thread.CurrentThread.ManagedThreadId}");

// Create a new thread, passing the method to be executed
Thread t = new Thread(Task);

// Start the thread
t.Start();

// Continue with other work on the main thread
Console.WriteLine("Main thread is doing other work...");

// Wait for the new thread to finish
t.Join();

Console.WriteLine("Main thread is done.");

Thread.CurrentThread.ManagedThreadId is a property in C# that provides a unique identifier for the current managed thread. This identifier is specific to the thread and can be used to distinguish it from other threads in the application.

C# Thread pass arguments

When a method requires parameters, you can pass them to the thread using a lambda expression. A lambda expression allows you to define a short inline method, which can capture variables from the outer scope.

static void Repeat(int n, string word)
{
    for (int i = 0; i < n; i++)
        Console.WriteLine(word);
}

In Main method

int n = 5;
string word = "c# thread";

// Pass arguments to the thread using a lambda expression
var t = new Thread(() => Repeat(n, word));
t.Start();

In this example, we want to pass two arguments (n and word) to the Repeat method that is executed on a new thread. Instead of using a separate delegate, we create an inline lambda expression:

() => Repeat(n, word)

This lambda expression captures the values of n and word from the surrounding scope and calls the Repeat method. When the thread starts with t.Start(), it executes the Repeat method with the provided arguments.

C# Thread.Sleep

In C#, the Thread.Sleep method is used to pause the execution of the current thread for a specified period of time. During this time, the thread is not executing any code, and it gives up its remaining time slice, allowing other threads to execute in its place.

Console.WriteLine("Main thread starts.");

// Simulating some work in the main thread
for (int i = 0; i < 5; i++)
{
    Console.WriteLine($"Main thread iteration {i + 1}");
    Thread.Sleep(1000); // Sleep for 1 second (1000 milliseconds)
}

Console.WriteLine("Main thread ends.");

C# Background and Foreground thread

In C#, there are two types of threads: background and foreground

  • Background threads do not prevent the process from terminating. If only background threads are running, the process will end as soon as the foreground threads have completed.
  • Foreground threads are those that keep the application running. When all foreground threads in a process have finished, the Common Language Runtime (CLR) ends the process.

By default, threads are foreground threads. You can change a thread to a background thread by setting the IsBackground property to true.

static void DoWork(int n)
{
    Thread.Sleep(n);
    Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} finished in {n} ms");
}

In Main method

Console.WriteLine("Started...");
for (var i = 0; i < 3; i++)
{
    var rand = new Random().Next(1, 1000);
    var t = new Thread(() => DoWork(rand)) { IsBackground = true };
    t.Start();
}
Console.WriteLine("Finished...");

In the example, a main program thread is created along with 3 background threads. The main thread runs the main program, while the background threads perform their tasks independently. These background threads do not prevent the process from terminating when the main thread completes.

C# Thread Join

In C#, the Thread.Join method is used to make the calling thread wait until the thread on which Join is called has finished executing.

In this example, we create a new thread and use Join to ensure the main thread waits for it to finish before continuing.

static void DoWork()
{
    Console.WriteLine("Background thread is working...");
    Thread.Sleep(2000); // Simulate work by sleeping for 2 seconds
    Console.WriteLine("Background thread work is done.");
}

In Main method

Thread t = new Thread(DoWork);
t.Start();

Console.WriteLine("Main thread waiting for background thread to finish...");

// Main thread will wait until thread t finishes
t.Join();

Console.WriteLine("Background thread has finished, now main thread continues.");

You can specify a timeout value to avoid waiting indefinitely for a thread to finish. If the thread doesn’t complete within the specified time, the calling thread will resume execution.

// Wait for the background thread, but only for 3 seconds
bool finished = t.Join(3000);

if (finished)
{
    Console.WriteLine("Background thread finished within 3 seconds.");
}
else
{
    Console.WriteLine("Background thread did not finish in time.");
}

The Thread.Join method is an essential tool for thread synchronization in C#. It helps coordinate the execution of multiple threads by blocking the calling thread until the target thread has finished.