Concurrency & Async programming in C#
Tags: csharp, tutorial, dotnet, community
Published: 2024-07-09 10:38:09


{% embed https://youtu.be/UNLdSsCWIXs %}

Hello everyone! Today, we're diving into some crucial concepts in C# that will help you write more efficient applications. We'll explore processes, threads, concurrency, and asynchronous programming. These topics might seem daunting initially, but don't worry; we'll break them down step by step. Without further ado, let's dive right in. 🏊‍♂️


### What is a Process? 💡

A process is essentially an instance of a program currently being executed. Think of it as a container that holds a program's code and its current activity. A process can be any application, such as Visual Studio or a web browser. Each process has its own memory space, ensuring that one process does not interfere with another.

### Process Components 🔧

- **Main Thread**: Each process has a main thread.
- **Memory Stack and Heap**: Each process has its own stack and heap, isolated from other processes.
- **Program Counter (PC)**: Keeps track of the number of executed code lines, particularly useful during context switching.


### What are Threads? 🧵

A process may consist of one or more threads, each with its own memory space. However, each thread only has a stack. These threads are often referred to as worker threads. 

- **Value Type Variables**: Saved in the stack.
- **Reference Type Variables**: Reference saved in the stack, value stored in the heap.

### Garbage Collection (GC)

As discussed in previous sessions, the garbage collector manages the heap. When a process is completed, its allocated space is returned, and the GC takes care of memory management.

## CPU Scheduling Algorithms 🖥️

### First Come First Serve (FCFS) 📋

The CPU executes processes in the order they arrive. While simple, this method can lead to starvation if a long process blocks shorter ones.

### Shortest Job First (SJF) 🏃

The CPU executes the shortest job first. While this can be efficient, it can also lead to starvation if shorter processes continually arrive, blocking longer ones.

### Round Robin (RR) 🎡

Each process is assigned a fixed time slot in a cyclical manner. This prevents starvation and ensures fair CPU time distribution.

## Round Robin Algorithm in Detail

Consider we have many processes, from P1 to many others. They go to the ready status and get queued in a first-come, first-served manner. The CPU begins running the first process. If the process is completed within the designated time period, it is terminated. If not, it is moved to the end of the queue.



### Synchronous Programming 🤔

In C#, there are two types of threads: the worker thread and the main thread. In each thread, we output something - "MT" for the main thread and "T1" for the worker thread. 

Here's an example code to demonstrate this:

```csharp
Thread thread1 = new Thread(() =>
{
    for (int i = 0; i < 1000; i++)
    {
        Console.Write("T1 ");
    }
});

thread1.Start();
thread1.Join();

for (int i = 0; i < 1000; i++)
{
    Console.Write("MT ");
}
```

In this example, the main thread writes "MT" 1000 times, and the worker thread writes "T1" 1000 times. Depending on the CPU's time quantum, you'll observe a combination of "MT" and "T1."


![Sync Programming](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wufwb62zua7mokb6vxng.png)



### Asynchronous Programming 🤔

In asynchronous programming, the main thread does not wait for the worker thread to complete before it continues working. This results in no blocked threads and ensures that your application remains responsive during long-running operations.

```csharp
Thread thread1 = new Thread(() =>
{
    for (int i = 0; i < 1000; i++)
    {
        Console.Write("T1 ");
    }
});

thread1.Start();

for (int i = 0; i < 1000; i++)
{
    Console.Write("MT ");
}
```

In this asynchronous example, we have context switching between the main and worker threads, so threads are not blocking each other.


![Async Programming](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2xrvfpibbd7dgoi6r25.png)



## Conclusion ✨

Understanding processes, threads, concurrency, and asynchronous programming is crucial for developing efficient and responsive C# applications. Processes are containers for your running programs; threads are the execution units within these processes; concurrency ensures multi-tasks progress simultaneously; and asynchronous programming helps keep your application responsive during long-running operations.

Thank you for reading! I hope this guide has clarified these important concepts for you. If you have any questions, please leave a comment below. Don't forget to like, and subscribe. Cheers, and happy coding!