Introduction to Multithreading

So far, we talked about Concurrency and we learned that concurrency is a general concept like “architectural style” in software architecture. It is possible to implement the given architectural style using multiple architectural patterns. No matter if you’re using CPU-intensive or I/O bound operations, they altogether create the world of “concurrency”.

Multithreading

Multithreading is a specific approach used to archive “concurrency” within a program. Well, as you understand, multithreading is a form of concurrency.

MultiThreading-Cncurrency

In software development, multithreading is a technique that allows multiple parts of a program to execute concurrency within a single process.

There are old-school and new ways of implementing multithreading in C#.

For old-school development, especially to support legacy code and to work with older versions of the .NET framework, we're using Thread class.

Guess what? If you want to understand Multithreading in more detail, my option is to start learning System. Threading namespace, especially the Thread class.

So, let's try to understand why we use Multithreading( Thread ) in our projects:

1. Responsive UI Applications

Running long-running tasks in the background: Keeps UI responsive while performing intensive operations like file downloads, database queries, or complex calculations.

Example: Launching a separate thread to load data in a web browser while allowing user interaction with other UI elements.

2. Data Processing and Parallelism

Accelerating computations by parallelizing tasks: Divides work into smaller chunks and executes them concurrently on multiple threads, leveraging multi-core processors.

Example: Analyzing large datasets or processing images in parallel for faster results in scientific computing or image editing applications.

3. Server Applications

Handling multiple client requests: Each client request can be handled on a separate thread, improving server responsiveness and scalability.

Example: A web server using threads to serve multiple concurrent requests.

4. Game Development

Managing game logic and physics: Threads can be used for game updates, rendering, physics simulations, and AI tasks, ensuring smooth gameplay.

Example: A game engine using separate threads for game logic, rendering, and audio processing.

5. Network Communication

Handling asynchronous network operations: Threads can efficiently manage incoming and outgoing network communications without blocking the main thread.

Example: A chat application using threads to listen for incoming messages and send outgoing messages simultaneously.

6. Asynchronous File I/O

Performing file operations without blocking the main thread: Threads enable reading and writing files concurrently with other tasks.

Example: A file backup application using threads to copy files in the background while allowing users to continue working.

7. Background Tasks and Scheduled Jobs

Executing tasks periodically or at specific times: Threads can run maintenance tasks, perform updates, or send notifications without user interaction.

Example: A system utility using threads to scan for viruses or clean up temporary files in the background.

Simple code example

using System.Threading;

// Method to run on a separate thread
void BackgroundTask()
{

    for (int i = 0; i < 10; i++)
    {

        Console.WriteLine("Background task: {0}", i);
        Thread.Sleep(1000); // Simulate work
    }
}

// Main method
void Main()

{
    Thread thread = new Thread(BackgroundTask);
    thread.Start();
    Console.WriteLine("Main thread continues...");
    Thread.Sleep(5000); // Wait for background task to finish

}

PS: Using the Thread class directly in your code indicates that you’re dealing with legacy code.

The Thread class was introduced in .NET 1.0 and started from .NET 2.0. We have ThreadPool to work with Threads.

Here's a comparison of Threadpool and Thread in C#.

ThreadPool

Purpose

Efficiently manages a pool of reusable threads for executing short-lived, asynchronous tasks.

Key Features of ThreadPool

  1. Managed by the CLR: Automatic thread creation, management, and destruction.
  2. Background threads: Threads terminate when all foreground threads exit.
  3. Limited control: Cannot set priority or control thread affinity.

Ideal for

  1. Short-lived, I/O-bound tasks (file access, network calls)
  2. Quick background operations
  3. High-volume, repetitive tasks

Thread

Purpose

Provides direct control over thread creation and execution for fine-grained management.

Key Features of Thread

  1. Explicit creation and management: Manually create, start, stop, and manage threads.
  2. Foreground or background: Configurable thread type.
  3. Full control: Set priority, thread affinity, and other properties.

Ideal for

  1. Long-running tasks
  2. Tasks requiring specific thread priority or affinity
  3. Custom synchronization and coordination
  4. Complex threading scenarios

When to Use Threadpool?

  • Short, asynchronous tasks
  • High-volume task execution
  • Simple background operations

When to Use Thread?

  • Fine-grained control over execution
  • Long-running tasks
  • Specific thread requirements
  • Complex synchronization scenarios

Best Practices

  • Start with Threadpool for most asynchronous tasks.
  • Use Thread for specific control needs or long-running operations.
  • Be mindful of thread overhead and the potential for resource contention.
  • Design for thread safety and synchronization to avoid race conditions.
  • Consider higher-level abstractions like Task Parallel Library (TPL) for simpler management in modern C# development.

Long story short, in modern software development, we’re implementing multithreading using ThreadPool. Multithreading is a better option when you deal with CPU-bound tasks and parallel processing. It allows multiple Threads to share a single CPU and Execute one after another, creating the illusion of simultaneous execution.

Conclusion

Multithreading is a form of concurrency that is used for CPU-intensive operations. You can achieve Multithreading using Thread( old-school) and ThreadPool( modern) classes. Parallel processing is a part of multithreading, and I'll talk about it in our next article.

This was just an introduction, and starting from the next tutorial, we'll talk about Multithreading in more detail.


Similar Articles