C# Multithreading
Multithreading in C# refers to the simultaneous use of several threads. One can multitask by following process. Time is saved by carrying out several tasks at once. We must employ the System.Creating multithreaded apps in C# using the threading namespace.
A program's execution path is referred to as a thread. Every thread specifies a different control flow. It is frequently beneficial to set up various execution routes or threads, with each thread carrying out a specific task, if your program requires difficult and time-consuming activities.
Lightweight processes are threads. Concurrent programming is a frequent application of threads that is implemented by contemporary operating systems. Threading improves application efficiency and reduces CPU cycle waste.
In C#, you may use the Thread class to start a new thread. Here is an example of how to start a new thread:
Program:
The following program will be:
using System;
using System.Threading;
class Program
{
static void Main()
{
// create a new thread
Thread t = new Thread(Worker);
// start the Thread
t.Start();
// do some other work in the main Thread
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread doing some work");
Thread.Sleep(100);
}
// wait for the worker thread to complete
t.Join();
Console.WriteLine("Done");
}
static void Worker()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Worker thread doing some work");
Thread.Sleep(100);
}
}
}
OUTPUT:
The Output for the following program will be:
![C# Multithreading](https://static.tutorialandexample.com/csharp/csharp-multithreading1.png)
In this example, the main Thread works on something else while a different thread runs the Worker method. To simulate work in both threads, utilize the Thread sleep function.
Program:
The following program will be:
using System;
using System.Threading;
class Program
{
static void Main()
{
//Queue a work item to the thread pool
ThreadPool.QueueUserWorkItem(Worker, "Hello, world!");
// do some other work in the main Thread
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread doing some work");
Thread.Sleep(100);
}
Console.WriteLine("Done");
}
static void Worker(object state)
{
string message = (string)state;
for (int i = 0; i < 10; i++)
{
Console.WriteLine(message);
Thread.Sleep(100);
}
}
}
OUTPUT:
The Output for the following program will be:
![C# Multithreading](https://static.tutorialandexample.com/csharp/csharp-multithreading2.png)
In this illustration, the main Thread works on something else while a thread from the thread pool runs the Worker function. The work item is queued to the thread pool using the ThreadPool.QueueUserWorkItem function. The state object can be used to send data to the worker method.
The simultaneous performance of several tasks or processes over a set period is known as multitasking. The Windows operating system illustrates multitasking because it can execute multiple processes simultaneously, such as Google Chrome, Notepad, VLC player, etc.
The operating system runs each of these programs simultaneously, utilizing a concept known as a process.
Every program, therefore, has logic, which is executed by threads. This single-threaded approach needs improvement. The program's processes are all executed sequentially by the single Thread in a synchronizing way.
Since the main Thread is now in the position of carrying out all of these methods, it does so one at a time.
Example:
The following program will be:
// C# program to illustrate the
// concept of single-threaded model
using System;
using System.Threading;
public class Geek {
// static method one
public static void method1()
{
// It prints numbers from 0 to 10
for (int I = 0; I <= 10; I++) {
Console.WriteLine("Method1 is : {0}", I);
// When the value of I is equal to
// 5 then this method sleeps for
// 6 seconds, and after 6 seconds
// it resumes its working
if (I == 5) {
Thread.Sleep(6000);
}
}
}
// static method two
public static void method2()
{
// It prints numbers from 0 to 10
for (int J = 0; J <= 10; J++) {
Console.WriteLine("Method2 is : {0}", J);
}
}
}
// Driver Class
public class Preethi {
// Main Method
static public void Main()
{
// Calling static methods
Geek.method1();
Geek.method2();
}
}
OUTPUT:
The Output for the following program will be:
![C# Multithreading](https://static.tutorialandexample.com/csharp/csharp-multithreading3.png)
Code Explanation:
Here, method 1 is first put into action. In method 1, the for loop begins at 0, and when the value of i equals 5, the function sleeps for 6 seconds before resuming and printing the remaining value until the waiting stage of method 2. When method 1 completes the assigned task, method 2 begins to operate.
Therefore, Multithreading is implemented to address the problem with the single-threaded approach. A process that uses several threads inside of a single process is known as multithreading. Here, each Thread carries out a different function. For instance, if a class contains two different methods that are called, using multithreading will cause each method to be run by a different thread.
The main benefit of multithreading is that it does numerous jobs simultaneously since it operates simultaneously. Additionally, since multithreading operates on the time-sharing principle, each Thread needs its amount of time to complete its task without interfering with the work of another thread. The operating system determines this time frame.
System.Threading Namespace:
The Programme.Classes and interfaces in the threading namespace are used to enable multithreaded programming. Additionally, classes are provided for synchronizing the thread resource. Below is a list of frequently used classes:
- Thread
- Mutex
- Timer
- Monitor
- Semaphore
- ThreadLocal
- ThreadPool
- Volatile etc.
What is a Process?
A corresponding process runs each programme. The term "background processes" is also used to describe a variety of processes that are constantly running in the background.
Thus, we have an operating system, and processes that run our applications are part of the operating System. The process internally uses a Thread to execute an application's code.
What is Thread?
- A Thread is often a quick process. To put it simply, a Thread is part of a process that is in charge of running the application code.
- Every process, by default, has one Thread, known as the Main Thread, which is in charge of running the application code. Therefore, every application is single threaded by default.
Note: In C#, the System is the class that contains all threading-related classes. namespace for threads.
Example to Understand Threading in C#:
- Let's look at an example to understand further threading in C#. The programme that comes next is essential. It has a Main method that prints a message on the Console window and a class called Programme.
CODE:
The following program will be:
using System;
namespace ThreadingDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome to Dotnet world!");
Console.ReadKey();
}
}
}
OUTPUT:
The Output for the following program will be:
![C# Multithreading](https://static.tutorialandexample.com/csharp/csharp-multithreading4.png)
Thread Class in C#:
- The Thread Class in C# provides a static property called CurrentThread that returns an instance of the currently running Thread, in this case, the Thread that is running the code for your application. The Thread class definition contains the following signature.
- As you can see, the CurrentThread static property's return type is Thread, therefore it will return a copy of the thread that is now active.
- Similarly, the Name non-static property allows us to set and retrieve the name of the presently running Thread.
- Note that the Thread is nameless by default. By using the Name field of the Thread class, you can give the Thread any name if you'd like. Therefore, alter the program as shown below, where we print and set the thread class's Name attribute.
Process and Thread
- A thread represents a module of the application, whereas a process represents the entire application. While the Thread is a lightweight component, the process is a heavy component. Because a thread runs inside a process, it might be referred to as a lightweight subprocess.
- A unique memory space is occupied each time you create a process. But a common memory space is shared by threads. The element of the operating system (or an operating system-level component) in charge of carrying out the program or application is called a process. Consequently, a process will be used to run every program or application.
Drawbacks of Single-Threaded Applications in .NET Framework?
The Main Thread is the only Thread in a single-threaded application that will run any logic or code that is included in the programme. Imagine, for the sake of illustration, that our programme contains three methods, each of which will be referred to as the Main method. Then, the Main Thread's solely responsible for carrying out these three techniques, or one at a time. The first technique will be put into action, and only when it has finished will the second method be put into action, and so on. Let's use an example to grasp this better. Change the program as indicated below.
By allowing you to run several threads concurrently within a single process using C#, you may boost the speed of your program and use contemporary multi-core CPUs. Threads are small, autonomous execution units that use the same memory as their parent process to complete tasks. I'll briefly overview C# multithreading in the paragraphs below, outlining its fundamental principles, thread creation and management, synchronization, and best practices.
1. Threads and Threading Basics:
C# gives you the ability to establish and manage threads.namespace by using the System. The primary Thread is automatically created once an application starts up. You can instantiate the Thread class and pass a function to be called as a parameter to add more threads. Start the Thread's execution by calling the Start() function.
2. Thread States:
Throughout their lifecycle, threads can exist in a variety of states, including:
Unstarted: The Thread has been started but has yet to run.
Running: The Thread is carrying out its programming.
The Thread is blocked because it is awaiting a resource or an event.
Suspended: Another thread has momentarily put the discussion on hold.
Stopped: The Thread's execution has come to an end.
3. Thread Synchronization:
Synchronization is necessary when many threads access the same resource to prevent race situations and guarantee data integrity. To manage thread access to shared resources, C# has several synchronization constructs like lock, Monitor, Mutex, Semaphore, and ManualResetEvent.
4. Using the lock Keyword:
The lock keyword locks down a particular code block so that only one Thread can run it simultaneously. It makes use of a monitor synchronization primitive. When one Thread enters a lock block, all subsequent thread attempts are halted until the initial Thread leaves the block.
5. Using Monitor:
The Monitor class's Enter, (), and Exit() methods give users more precise control over synchronization. Using the Pulse() and PulseAll() methods, you can lock on a particular object and alert other threads waiting for the same object when a condition is satisfied.
6. Using Mutex:
A synchronization primitive called a Mutex (short for mutual exclusion) enables several threads from the same or distinct processes to share resources safely. Until the owning Thread releases it, any other threads attempting to acquire it will be stopped.
7. Using ManualResetEvent:
A ManualResetEvent is a basic for synchronization that permits signal-based communication between threads. Threads can wait for a signal to be established before continuing their work when it is signaled. It doesn't explicitly reset from the signaled state.
Advantages of Multithreading:
- It runs numerous processes concurrently.
- Maximize the use of the CPU's capabilities.
- Sharing of time between various processes.
Conclusion:
In conclusion, C# multithreading is a crucial feature that helps programmers to make the most of contemporary multi-core processors and produce quick, efficient applications. C# multithreading gives up many opportunities for effectively managing computationally heavy jobs, I/O-bound procedures, and concurrent data processing by allowing several threads to run concurrently within a single process.
But multithreading has its difficulties and complexity. To prevent race situations, deadlocks, and data corruption, adequate thread synchronization and safety must be considered carefully. To appropriately limit access to shared resources, developers must be familiar with synchronization components, including lock, Monitor, Mutex, Semaphore, and ManualResetEvent.
The Task Parallel Library (TPL) for high-level parallelism, async/await for asynchronous programming, and the thread pool for efficient thread reuse are just a few of the tools and techniques available in C# to make multithreaded programming simpler. Asynchronous programming allows programmers to create responsive apps with lengthy tasks that can be managed without pausing the main Thread.
Essential rules include minimizing shared state, utilizing Thread pooling for resource effectiveness, and avoiding blocking actions in UI threads. Additionally, programmers should exercise caution when employing thread aborts and, whenever possible, choose gentle thread termination strategies.
Overall, C# multithreading allows programmers to build dependable, fast-running systems that effectively use current hardware capabilities. Developers may confidently take on the challenges of concurrent programming in C# and provide top-notch user experiences by having a firm grasp of multithreading fundamentals, synchronization mechanisms, and best practices.