Wednesday, August 27, 2008

How to implement Threading in C#.NET?

What is Threading?

A Thread is an independent execution path for a code that can run concurrently with other execution paths i.e. other threads. All threads within a single application are logically contained within a Process – the operating system unit in which an application runs.. Application performance can be improved by executing multiple code paths simultaneously i.e. executing multiple threads simultaneously. This phenomenon of executing multiple threads simultaneously is called as Multi-threading. Multi-threading is often used in applications to enhance the application performance. Usually multiple threads that are executed are independent of each other to enhance the performance by reducing dependencies.

C# supports multi-threading of applications. A C# programs (let’s consider a console application) starts in a single thread created by the CLR and the OS i.e. the “main” thread. Then user can invoke multiple threads from this main thread to create a multi-threaded application. Let’s consider the example given below:

C# Threading Example:



using System;
using System.Threading;

namespace ThreadingSamples
{
class Program
{
static void Main(string[] args)
{

Program pg = new Program();
Thread thread = new Thread(new ThreadStart(pg.Fun));
thread.Name = "Thread_1";
thread.Start();

Thread.CurrentThread.Name = "Main_Thread";
pg.Fun();

Console.ReadLine();
}

public void Fun()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}


Output:


In the above given sample C# code, the main thread is invoked (also called as spawned) by the CLR. In the main thread we have created another thread called “Thread_1” and invoked the thread using the thread.Start() method. Note that we need to include the System and System.Threading namespaces for implementation of threading in C#. A separate copy of the variables in the “Fun” method is created for each thread (which resides on each threads memory stack). We have created an object of “ThreadStart”. Basically ThreadStart is a delegate that invokes the method supplied to it. In this example we have invoked a method “Fun” that does not accept any arguments. But if we want to call a function that accepts arguments then we have to use ParameterizedThreadStart instead of ThreadStart. The threads can be named, as we have named the thread “Main_Thread” and “Thread_1”.

How Threading Works in C#?

Multithreading is managed internally by a thread scheduler, a function the CLR typically delegates to the operating system. A thread scheduler ensures all active threads are allocated appropriate execution time, and that threads that are waiting or blocked such as on an exclusive lock, or for user input do not consume CPU time. Usually time-slicing mechanism is used to schedule the thread execution.


What is a Thread Safe Function?

A method/function that can ONLY be executed by a Single thread at a time is called as a Thread Safe function. The function “Fun” that we have seen in the above code sample is not thread safe, since any number of threads can access/execute this function simultaneously. When we talk about a thread safe function, the question arises- Why do we require a thread safe function? A thread safe function is required usually when we share variables across threads such as static variables or when we want that an object should be manipulated by a single thread at a time to maintain the data integrity. Let’s see an example of Thread Safe function…

C# Thread Safe Function:




class Program
{
static void Main(string[] args)
{

Program pg = new Program();
Thread thread = new Thread(new ThreadStart(pg.Fun));
thread.Name = "Thread_1";
thread.Priority = ThreadPriority.Normal;
thread.Start();

Thread.CurrentThread.Name = "Main_Thread";
pg.Fun();

Console.ReadLine();
}

public void Fun()
{
// The C# “lock” statement will lock the execution of the thread
lock(sync)
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}

In the above sample code, the C# “lock” statement is used to lock the execution of the block when one thread is executing it. This means that ONLY one thread at a time can enter this Lock block for execution. Any other thread trying to enter will have to wait until the first thread completes its execution. Thus in this way we can make a function as a thread safe function. This can even be achieved by using Semaphores, Mutex etc. We do set priorities for threads in execution. Various values for thread priority are AboveNormal, BelowNormal, Normal, Highest, and Lowest.

Hope this helps you! Your comments are always welcome !

1 comments:

Danilo Garcia said...

I know this is old but i never really understand what threads are. But now it seems simple.

Thanks for the brief!

Post a Comment