Multi-threading in C#

05 maart 2021 om 10:00 by ParTech Media - Post a comment

In the present world, most of our tasks are being done using computers. Computers have a wide array of benefits in every field, be it mechanical, electrical, civil designs, load testing, performance analysis, etc. They display their utility through web applications, desktop applications, and cloud-based apps.

It is a universal fact that computers have significantly contributed to mankind by making several tasks simpler and easier than doing them manually. Having said that, one of the best features of a computer is its multitasking capability. Most of us browse websites while writing a document in Microsoft Word. This is multi-tasking.

Similarly, we have multi-threading in C# language, where you can run multiple processes in parallel. In this post, we are going to understand what is multithreading in C# and how to achieve it with the help of a sample project.

Table of contents

  1. What is Multi-Threading?
  2. Multi-Threading in C#
  3. Life Cycle of a thread
  4. Frequently accessed member/property of a thread
  5. Practical application of multi-thread
  6. Conclusion

What is Multi-Threading?

Think of your personal Windows-based computer. As soon as you power on the computer, it boots and loads the desktop. Now, you want to copy some files from one folder to another. Imagine while you are copying the files, you cannot use any other application on Windows. Is this productive for you? No, right. It sounds really cumbersome. Fortunately, Windows can handle multiple processes at a time. This means users can work on multiple applications at the same time.

Similarly, applications that are written using C# programming language (.Net), can also handle multiple processes in parallel. When a C# based program gets executed, it will initially be a single thread. This means all the codes of the application are executed using the same thread in the same sequential order (as how the code is written).

Along with this, C# provides an option to execute the code that can be run in parallel using a multithreading concept, where the process/application can have multiple threads invoked within it.

Multi-threading in C#

Threads are lightweight processes that act as a path through which a process can be executed. Every process/application runs by default with a single thread. The entire code of the application gets executed sequentially in a single thread.

Multithreaded applications introduced the capability to process the independent code concurrently in more than one thread. Multithreading helps to reduce the time of execution, and also makes use of the CPU power in an optimum level.

System.Threading namespace contains the classes and interface which enables multithreading in an application.

Life Cycle of Thread

Here’s the life cycle of a thread -

Unstarted State - State at which the instance of the thread is created but hasn’t yet started to run. In other words, Start() method of the Thread is not being called.

Eg - var thread = new Thread();

Ready State - A thread that is ready to run is in a runnable/ready state. This means an instance of the thread is created and it is ready to run at any moment.

Running State - As the name implies, the thread that is running is termed to be in a running state.

Non-Runnable State - State at which the thread is not executable. Below are few states which are considered non-runnable when,

  • ​ Sleep() method of the thread is active
  • ​ Wait() method of the thread is active
  • ​ Suspend() method of the thread is called
  • ​ Waiting for I/O Operations

Dead State - When the thread completes the task assigned to it, it is considered to be in a dead state.

Frequently accessed member/property of a thread

Methods that are frequently accessed

  • public void Start() - This method is invoked to start a thread.
  • public static void Sleep(int millisecondsTimeout) - This method is used to sleep the current thread for the defined millisecond period. As the method is static, it is invoked with the class name directly (Thread.Sleep(2000)).
  • public void Suspend() - Suspends the thread. It does not affect if invoked when the thread is already suspended. Also, it throws an exception when invoked before starting or after the thread is dead.
  • public void Resume() - Resumes the suspended thread. It throws an exception when invoked and the thread has not started or when it is not suspended.
  • public void Abort() - Terminated the calling thread.

Properties that are frequently accessed.

  • public string Name { get; set; } - Provides the name of the thread object. Also, users can assign thread names at run time.
  • public bool IsAlive { get; } - Provides whether the thread object is alive. It returns true or false. It is a read-only property.
  • public ThreadState ThreadState { get; } - Provides the state of the thread. It returns the state with ThreadState as the return type.
  • public ThreadPriority Priority { get; set; } - Users can assign as well as read the priority of the thread instance using this property. Priority can be set with the type ThreadPriority(enum).

Practical application of multi-thread

In this section, let's create a simple console application and implement threading in it.

Step 1

Create a console application and provide a valid name for the solution.

Step 2

Open the program.cs file that comes with the solution and create two new methods; one named as ForwardNumbering and another one as ReverseNumbering. And implement the code to do forward and reverse numbering operations.

Step 3

Run the code and observe the output. First, the forward numbering will run, then the reverse numbering gets executed.

Step 4

Now, let's try to invoke both the methods in-parallel using threads.

Step 5

Run this code and observe the results. You will notice that the reverse and forward are getting executed in random order.

Step 6

Let's try to make one of the threads to a Non-runnable state (Sleep) for a few seconds. If the value of the iterator reaches 3, then we are sleeping that particular thread for 5 seconds.

Step 7

Run the code and observe the results. You will notice that after the forward (up to 2) no other data has been written for forwarding until the reverse gets completed. So, the thread that was carrying out the operations forward was in the sleep state.

Conclusion

With the advent of multi-threading, it has become easier to reduce the time taken for the execution of a task. Also, it increases the volume of data/code that can be processed at a single time. The best part is C# provides the options to track the state, destroy, start threads as and when required by the user.