Earlier computers were based on batch processing. In batch processing, a central processing unit (CPU) was capable of doing one task at a time. If a CPU has to take long time to execute a task, the other processes would have paused. In that case the whole machine would freeze. Things could get worse if there is a bug in the running task. The only solution eas to restart the machine.
The solution of this problem is Thread. In modern operating systems each application runs in its own process. If this application affects anything the other processes will remain unaffected. Each process has its own "Virtual Memory." Each process is allowed to run for a particular time period. When this time period is over, thread is paused, its state is saved, and the operating system switches to another thread. It is called "Context Switching" Actually at one time, only one process runs on CPU. But today, as computing is so much faster and powerful and context switching happens so fast, we feel that computer is executing many tasks at a time. In .NET, for threading we use Thread Class. It can be found in System.Threading namespace.
Note: Always import System.Threading in your project before using Thread Class.
Example: This is a simple example of threading,
Common Mistake: When you call a function in Thread class, people commonly call it parenthesis like (). Do not call it with parenthesis. Just write down the name of the method.
Output
The above example shows an example of using the Thread class to run a method. The Console class synchronizes the use of the output stream for you so you can write to it from multiple threads. Synchronization is the mechanism of ensuring that two threads don’t execute a specific portion of your program at the same time. In the case of a console application, this means that no two threads can write data to the screen at the exact same time. If one thread is working with the output stream, other threads will have to wait before it’s finished.
Join Method:
Join is a synchronous method that blocks the other thread until the thread which is on the CPU terminates.
Example:
Code:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Threading;
-
- namespace SimpleThread
- {
- class Program
- {
-
- public static void ThreadMethod()
- {
-
- for (int i = 0; i <= 5; i++)
- {
- Console.WriteLine("Thread 0");
-
- }
-
- }
- public static void ThreadMethod1()
- {
-
- for (int i = 0; i <= 5; i++)
- {
- Console.WriteLine("Thread 1");
-
- }
- }
-
- static void Main(string[] args)
- {
-
-
- Thread thread = new Thread(new ThreadStart(ThreadMethod));
- thread.Start();
- Thread thread1 = new Thread(new ThreadStart(ThreadMethod1));
- thread1.Start();
- Console.ReadKey();
- }
- }
-
- }
Output 1
Output 2
Note
Every time you compile the code, you might geta different answer. So do not worry about that. Now let's look what happes with the use of Join method.
Code
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Threading;
-
- namespace SimpleThread
- {
- class Program
- {
-
- public static void ThreadMethod()
- {
-
- for (int i = 0; i <= 5; i++)
- {
- Console.WriteLine("Thread 0");
-
- }
-
- }
- public static void ThreadMethod1()
- {
-
- for (int i = 0; i <= 5; i++)
- {
- Console.WriteLine("Thread 1");
-
- }
-
- }
-
- static void Main(string[] args)
- {
-
-
- Thread thread = new Thread(new ThreadStart(ThreadMethod));
- thread.Start();
- thread.Join();
- Thread thread1 = new Thread(new ThreadStart(ThreadMethod1));
- thread1.Start();
- Console.ReadKey();
- }
- }
-
- }
Explanation
The only change is the thread.Join() method. Now the second thread will not execute until first thread terminates.
Output
Now after every compilation you will get this result.
Foreground and Background Thread
Foreground thread keeps your application alive. Once foreground thread ends, application ends and background threads also terminates. By default all threads are foreground.
Note: To make a thread background just make the isBackground property true. If this property is false of a thread, it means it is foreground.
e.g
Thread t=new Thread();
t.IsBackground = true;
Code
- class Program
- {
- public static void ThreadMethod()
- {
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("Foreground Thread");
- Thread.Sleep(300);
- }
- Console.WriteLine("Foreground thread is terminated");
- }
- public static void ThreadMethod1()
- {
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("Background thread");
- Thread.Sleep(200);
- }
- }
-
- static void Main(string[] args)
- {
- Thread thread = new Thread(new ThreadStart(ThreadMethod));
- thread.Start();
- thread.Join();
- Thread thread1 = new Thread(new ThreadStart(ThreadMethod1));
- thread1.IsBackground = true;
- thread1.Start();
-
- }
- }
Output
Foreground thread will execute 10 times and application will terminate.
Explanation
I have used Join method with which foreground thread will execute until it terminates. As second thread is background and background thread executes till the execution of foreground thread. As foreground thread terminates, background thread also terminates. So when the above code executes, the first thread executes ten times and then application end.
Note
In Console Application, use Console.ReadKey() for screen .The background thread will also execute 10 times because Console.Readkey() behaves as foreground thread. And we know that background thread executes until foreground thread is alive.
ParameterizedThreadStart
We can pass data through start method of a thread. For this purpose, we use ParameterizedThreadStart delegate instead of simple ThreadStart delegate.
Example
- class Program
- {
- public static void ThreadMethod(object o)
- {
- for (int i = 0; i < (int) o; i++)
- {
- Console.WriteLine("thread Proc{0}", i);
- }
- }
- static void Main(string[] args)
- {
- Thread thread = new Thread(new ParameterizedThreadStart(ThreadMethod));
- thread.Start(5);
- Console.ReadKey();
- }
- }
OutPut
thread proc0
thread proc1
thread proc2
thread proc3
thread proc4
Explanation:
In that case, value is passed to threadMethod as object, you can cast it to any other type.
Thread Static Attribute
By making a field or data member with the thread static attribute each thread gets its own copy of field.
Example
- class Program
-
- {
- [ThreadStatic]
- public static int field = 0;
- static void Main(string[] args)
- {
- new Thread(() =>
- {
- for (int i = 0; i < 10; i++)
- {
- field++;
- Console.WriteLine("thread 1:{0} ", field);
- }
- }).Start();
- new Thread(() =>
- {
- for (int i = 0; i < 10; i++)
- {
- field++;
- Console.WriteLine("thread 2:{0} ", field);
- }
- }).Start();
- Console.ReadKey();
- }
- }
Out put:
With the ThreadStaticAttribute applied, the maximum value of field becomes ten. If you remove it, you can see that both threads access the same value and it becomes twenty.