Multithreading in C#: A Step-by-Step Guide
In this article, we will be discussing multithreading in C#. Multithreading is a powerful concept in programming that allows you to run multiple tasks simultaneously in a single program. This can greatly improve the performance of your applications and make them more responsive.
Let’s start by defining what multithreading is and how it works. Multithreading is a process where multiple threads are executing independently in a single program. Each thread has its own execution context and operates independently of other threads. This allows you to run multiple tasks in parallel, improving the performance and responsiveness of your applications.
We will be building a simple project to demonstrate the concepts of multithreading in C#. To get started, create a new C# Console Application in Visual Studio and name it “MultithreadingDemo”.
Also, check out our Tiny C# Projects book! Chapter 8 is all about Asynchronous programming and will contain an extensive project and an in-depth explanation of everything asynchronous programming!
Defining a Task
The first step is defining a task we want to run in a separate thread. We’ll create a simple task for this demonstration that adds two numbers. Here is the code for our task:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System; using System.Threading.Tasks; namespace MultithreadingDemo { class Program { static void Main(string[] args) { Task task = new Task(() => { Console.WriteLine("Running task in separate thread..."); int result = AddNumbers(5, 10); Console.WriteLine("Result of addition: " + result); }); task.Start(); Console.WriteLine("Main thread is done."); Console.ReadLine(); } static int AddNumbers(int a, int b) { return a + b; } } } |
Looks great; let us break down this project on a step-by-step basis.
Our project. Step-by-step
- Including namespaces:
The using
keywords are used to include the required namespaces in the program. The System
namespace contains basic classes and types that are used in most .NET applications, and the System.Threading.Tasks
namespace provides classes for working with tasks in a multithreaded environment.
1 2 |
using System; using System.Threading.Tasks; |
- Define the class
Program
:
The class Program
defines the main class of the program. This class contains the main logic of the program.
1 2 3 4 |
namespace MultithreadingDemo { class Program { |
- Define the Main method:
The Main
method is the program’s entry point, and it is called when the program is executed. The static
keyword means that the method can be called without creating an instance of the class, and the void
keyword indicates that the method does not return any value. The args
parameter is an array of strings that can be passed to the program when it is executed.
1 2 |
static void Main(string[] args) { |
- Create a Task object:
The Task
object is created by calling the Task
constructor and passing an anonymous function (also known as a lambda expression) as an argument. This anonymous function is executed in a separate thread when the task is started.
1 |
Task task = new Task(() => { |
- The anonymous function within the Task constructor:
The anonymous function contains the code that is executed in a separate thread. The first line writes “Running task in separate thread…” to the console, and the second line calls the AddNumbers
method to perform an addition operation. The result of the addition is stored in a local variable, and the value is written to the console.
1 2 3 4 |
Console.WriteLine("Running task in separate thread..."); int result = AddNumbers(5, 10); Console.WriteLine("Result of addition: " + result); }); |
- Start the Task:
The task.Start()
method is called to start the task. This method launches a separate thread that runs the anonymous function.
1 |
task.Start(); |
- The Main thread continues to run:
The main thread continues to run even after the task is started. The line Console.WriteLine("Main thread is done.")
writes “Main thread is done.” to the console.
1 |
Console.WriteLine("Main thread is done."); |
- Wait for user input:
The line Console.ReadLine()
is used to wait for user input before the program exits. This is used to allow the task to complete before the program terminates.
1 2 |
Console.ReadLine(); } |
- Define the
AddNumbers
method:
The AddNumbers
method takes two integers as arguments and returns their sum. This method is called by the anonymous function in the Task object.
1 2 3 4 |
static int AddNumbers(int a, int b) { return a + b; } |
- End of the class definition:
The end of the class definition is indicated by the closing curly braces }
. The last brace indicates the end of the Program
class, and the closing brace after the namespace
statement indicates the end of the MultithreadingDemo
namespace.
1 2 |
} } |
We first created a new instance of the Task
class. The Task
class provides a way to run a task in a separate thread. In the constructor, we passed a delegate that defines the work that the task should perform. In this case, we wrote a simple method that adds two numbers.
Perfect, next step, let us start this.
Starting the Task and Observing our Results
Now that we have defined the task, we can start it by calling the Start
method on the Task
object. This will run the task in a separate thread. In the Main
method, we call the Start
method on the Task
object we just created.
If you run the program, you will see that the task runs in a separate thread, and the main thread continues to run. The output should look something like this:
1 2 3 |
Main thread is done. Running task in separate thread... Result of addition: 15 |
This demonstrates how you can run a task in a separate thread using the Task
class in C#. The main thread continues to run and outputs “Main thread is done.” while the task runs in a separate thread and outputs “Running task in separate thread…” and “Result of addition: 15”.
Great! However, this might look an awful lot like asynchronous programming to you. And for sure, that is understandable, but let me explain why it is not the same.
Differences and similarities between multithreading and asynchronous programming.
Multithreading and asynchronous programming are often used interchangeably, but they are not exactly the same thing. Multithreading involves running multiple threads in parallel, while asynchronous programming involves executing tasks in a non-blocking way, allowing the program to continue executing other tasks while the asynchronous task is running in the background.
One similarity between multithreading and asynchronous programming is that they both allow you to run multiple tasks simultaneously, improving the performance and responsiveness of your applications.
In C#, asynchronous programming can be implemented using the async
and await
keywords. This makes it easier to write asynchronous code and provides a cleaner syntax compared to traditional multithreading.
If you want to learn more about asynchronous programming in C#, check out our article on asynchronous programming in C#!
And that’s it! With these concepts in mind, you should now understand the difference and similarities between multithreading and asynchronous programming in C#.
Conclusion: Multithreading in C#: A Step-by-Step Guide
In conclusion, multithreading is a powerful concept that can greatly improve the performance of your applications. The Task
class in C# provides a simple way to run tasks in separate threads, making it easier to take advantage of multithreading in your applications. By following the steps in this article, you should now understand how to implement multithreading in C#.
And don’t forget that when in doubt, you can always refer to this article to help you understand to use Multithreading in C#.