C# Multithreading

C# Multithreading is a programming concept where multiple threads (smaller units of execution) run concurrently within a program, allowing tasks to be performed at the same time. multithreading allows a program to perform more than one task at the same time, improving performance, especially in CPU-bound or I/O-bound operations.

Benefits of Multithreading

1. Improved Performance: Especially on multi-core systems, threads can run on separate processors or cores, improving execution speed.

2. Responsiveness: In GUI applications, multithreading allows background tasks (e.g., file download, database queries) to run without freezing the UI thread.

3. Better Resource Utilization: Can make better use of system resources by utilizing CPU cores more effectively.

Example:


using System;
using System.Threading;

class MyProgram
{
    // Method that will be executed by the new thread
    static void PrintNumbers()
    {
        for (int i = 1; i <= 10; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(1000);  // Simulate some work (e.g., waiting for I/O)
        }
    }

    static void Main()
    {
        // Creating a new thread and passing the method to execute
        Thread thread = new Thread(PrintNumbers);
        
        // Starting the thread
        thread.Start();

        // Main thread continues to execute while PrintNumbers runs in the background
        Console.WriteLine("Main thread is running concurrently with the new thread.");
        
        // Wait for the new thread to finish before exiting the program
        thread.Join();
        
        Console.WriteLine("All threads completed.");
    }
}

Explanation:

  • A thread can be created by instantiating the Thread class and passing the method to be executed.
  • Use the Start() method to begin the thread's execution.
  • Use the Join() method to block the main thread until the worker thread completes its task.

Example: two threads print numbers concurrently.


using System;
using System.Threading;

class MyProgram
{
    // Method to print numbers 1-5
    static void PrintNumbers()
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(1000);  // Wait for 1 second
        }
    }

    static void Main()
    {
        // Create and start two threads
        Thread thread1 = new Thread(PrintNumbers);
        Thread thread2 = new Thread(PrintNumbers);
        
        thread1.Start();
        thread2.Start();

        // Wait for both threads to finish
        thread1.Join();
        thread2.Join();

        Console.WriteLine("Both threads have finished.");
    }
}

Output:

1
1
2
2
3
3
4
4
5
5
Both threads have finished.

Example: Using Task makes handling threads easier


using System;
using System.Threading.Tasks;

class MyProgram
{
    static async Task PrintNumbersAsync()
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine(i);
            await Task.Delay(1000); // Asynchronous wait
        }
    }

    static async Task Main()
    {
        // Start the async task
        var task = PrintNumbersAsync();

        Console.WriteLine("Main thread is running concurrently with the async task.");

        // Wait for the task to finish
        await task;

        Console.WriteLine("All tasks completed.");
    }
}

Note: Modern C# practices like Task and async/await have made handling concurrent tasks much more intuitive and safer compared to traditional threading.

Output:

1
Main thread is running concurrently with the async task.
2
3
4
5
All tasks completed.