Basics of C# Threading
Most of the modern applications are multithreaded and support concurrency. The simplest definition of a multithreaded application is that an application which can perform multiple tasks concurrently. An excellent definition of a multithreaded application is the Microsoft’s word processor. Multiple tasks are being performed in parallel by the word processor. For instance, a writer types in the word document. Meanwhile spell check is runs in the background which informs the writer that he has typed a wrong spellings of a word, similarly dictionary is running in the background. In short, multiple tasks are being completed simultaneously.
In C#, threads are used to implement concurrency. The basic definition of thread is: “Smallest path of execution that can run independently”. A program is represented as a process in memory which provides an isolated environment for the program to run. If a program has multiple threads, they run inside process’ isolated environment and share the process resources such as memory. Multiple threads can be useful in such scenarios; for instance one thread can fetch the records from the database and the other thread can display it.
Learn basics of C# at Udemy.com
Implementing C# threading
Creating a thread in C# is a straight forward task. System.Threading namespace contains Thread class that can be used for creating a thread. It is shown below:
Thread newthread = new Thread(MethodDelegate)
Here ‘newthread’ is a variable of class Thread. The constructor of a thread class takes a delegate to the method (Only method name should be passed, no delegate), which has to be run in a new thread.
In order to run the thread, Start method should be called on the thread in the following way:
newthread.Start();
This would start executing the thread in parallel to the method from which this Start method is called. In other words, the method whose delegate was passed to newthread object would run in parallel to the method in which Start is called. This concept has been demonstrated realistically in the following example.
Suppose there is a method which displays a simple dash ‘-’, thousand times. This method is named DisplayDash and has following definition:
public static void DisplayDash() { for (int i = 0; i < 1000; i++) { Console.Write("-"); } }
In order to create a thread which can run this method in parallel to the Main method, main method has been modified as follows:
public static void Main() { Thread tdash = new Thread(DisplayDash); tdash.Start(); for (int i = 0; i < 1000; i++) { Console.Write("|"); } Console.ReadLine(); }
In the main method a new thread ‘tdash’ has been created using constructor of the Thread class. Delegate to DisplayDash method has been passed to the constructor. When Start is called on the ‘tdash’ thread, DisplayDash method would start executing in parallel with the Main method. In the main method, a loop prints ‘|’ symbol thousand times. So, what actually would happen is that since both loop in the DisplayDash method and the one in the Main method would execute concurrently (Both are running in parallel threads), therefore, CPU would regularly swap the console between two threads and the output displayed would contain irregularly patterns of dashes ‘-’ and ‘|’ symbols as shown below:
To Study more about C# and threading, take a course at Udemy.com
C# Thread Join
Join is used to wait for a thread to complete its execution before moving to the next statements in the calling method. The method from which Join is called waits for completion of the thread ON which join is called. If following changes are made in the Main method, the Main method would wait for ‘tdash’ thread to complete its execution before executing itself any further.
public static void Main() { Thread tdash = new Thread(DisplayDash); tdash.Start(); tdash.Join(); for (int i = 0; i < 1000; i++) { Console.Write("|"); } Console.ReadLine(); }
In the above Main method, under the Start method, Join method has been called on ‘tdash’ thread which will block further execution of Main method (which is also running on a thread, called Main thread in C#), till ‘tdash’ thread completes its execution. In the console output first dash ‘-’ would be displayed thousand times and then the Main method would display ‘|’ symbol. This time the output would look like this:
For more C# tutorials, Check this course
Passing Values to threads
In previous examples a simple parameter-less delegate has been passed to the Thread constructor and no parameters were passed to the method. There are two ways to pass values to a thread:
1- Using Lambda Expressions with Action delegate
2- Using Start Method.
- Using Lambda Expressions
Suppose there is a method called DisplaySymbol which displays the string type symbol passed to it. The definition of DisplaySymbol is as follows:
public static void DisplaySymbol(string s) { for (int i = 0; i < 1000; i++) { Console.Write(s); } }
In order to call this method with parameter from the Main method, following code can be used inside the main method:
Thread tdash = new Thread(()=> DisplaySymbol("#")); tdash.Start(); for (int i = 0; i < 1000; i++) { Console.Write("|"); } Console.ReadLine();
Here, inside the Constructor of the main method, a lambda expression is being used to call the Action delegate DisplaySymbol with parameter string “#”. After that, a loop in the Main method displays “|” symbol. The output would be again an irregular pattern of “#” and “|” due to concurrency of Main thread and ‘tdash’ thread.
- Using Start Method
Start method can be used to pass only a single parameter to a method. In order to pass values in the Start method, the parameter type of the DisplaySymbol method must be object and it should contain only one parameter. DisplaySymbol method from the last method can be modified as follows:
public static void DisplaySymbol(object s) { string symbol = s.ToString(); for (int i = 0; i < 1000; i++) { Console.Write(s); } }
In the main method, the parameters can be passed in the Start method as follows:
Thread tdash = new Thread(DisplaySymbol); tdash.Start("#"); for (int i = 0; i < 1000; i++) { Console.Write("|"); } Console.ReadLine();
Passing values using Start method has two disadvantages: First, only one parameter can be passed via Start method. Secondly, the object parameter in the called method has to be cast into the respective type as string in this case.
For thread Synchronization and other interesting C# thread concepts, take this tutorial
Recommended Articles
Top courses in Development
Popular topics
Empower your team. Lead the industry.
Get a subscription to a library of online courses and digital learning tools for your organization with Udemy Business.