Multithreading in .net by oraclequest

Introduction

This article is about muilti – threading concept in .NET explained using C# as programming language.

Multi threading is an important aspect that needs a special attention while building very huge system, especially when there is a trade off between efficiency (how fast the system works?) and performance (how correctly the system works?). With appropriate usage of Multi threading very high performance application can be developed and build.

What is threading?

Each application/program that is running in the system is a process. Each process consist of one or more thread. These process can whole or part of the application/ program. A thread is a set of instruction or specific section of application that executes independently within the application or system. This can be also thought as the context in which code runs. So threads are basically light weight processes responsible for multitasking within a single application. Usually OS takes care of scheduling and execution of various threads.

What is Multi threading?

When the system is build on various threads to perform multiple tasks to achieve parallelism and improve the efficiency of the system. This is the ability of any system to do multiple tasks simultaneously. Threads are implement when there are situations in which more then one task at a time need to be completed.

Some of the benefits of threading are mentioned as follows:

  • Using threads the long duration tasks in application can be processed at the background
  • User interface can be made more appealing so that there is some task performed during various events like when the user clicks button for the processing some action a progress bar can be shown to show the progress of activity.
  • Speed of the application can be increased.
  • Threads can be useful in situations where there are gaps between tasks waiting for some event such as user input, file read, or receipt of data over the network. During the situation we can release various precious resources like memory usages etc

And many other advantages can be achieved using multiple threading.

Some Threading Model Background
There is lot of material available about various threading model, Let discuss some of the models that are commonly supported by win32 environment.

Single Thread Model 
In this type of thread model only one thread is used to run the process remaining process needs to wait . The other processes must wait for the current execution of the thread to complete. The main disadvantage of this model is system idle time and long time to complete of small task.

Apartment Thread Model (Single Thread Apartment Model)
In this model we can have multiple threads executing with in an application. In single threaded apartment (STA) each thread is isolated in a separate apartment underneath the process. Each process can have multiple apartments that can share data between these apartment. Here the application is responsible for defining the time duration of each thread execution under these apartment. All requests are serialized through the Windows message queue such that only a single apartment is accessed at a time and thus only a single thread will be executing at any one time. Advantage of this model over single threaded is that multiple tasks can be processed at one time on the users request instead of just a single user request. This model still lack in performance as it is serialized thread model, task will be performed one after another.

Multi Thread Apartment Model (Free thread Apartment Model)
The Multi Threaded Apartment (MTA) model has a single apartment created underneath the process rather than multiple apartments. This single apartment holds multiple threads rather than just a single thread. No message queue is required because all of the threads are a part of the same apartment and can share. These applications typically execute faster than single threaded and STA because there is less system overhead and can be optimized to eliminate system idle time. These types of applications are complex to program as thread synchronization should be provided as part of the code to ensure that threads do not simultaneously access the same resources. A race condition can occur for the shared resource. Thus it is completely necessary to provide a locking system. When locking is provided this can result in a deadlock of the system.

How does multi-threading work in .NET?

By nature and architecture .NET is a multi-threaded environment.

 

Various action that are taken after the creation of threads are explained in the following sections.

Creating Threads :
Create new instance of Thread object. Thread constructor accepts one parameters which is delegate

Thread dummyThread = new Thread( new ThreadStart(dummyFunction) );

Executing Thread:
To run this thread us the method start provided by Threading namespace

DummyThread.Start ();

Joining Threads:
There is always the requirement to join thread specially when a thread depends on some other thread for completing its task. Lets assume that DummyThread has to wait for DummyPriorityThread to complete its task and then run again. In this case we need to do the following:

DummyPriorityThread.Join() ;

Suspending Thread:
This will suspend the thread for the given number of seconds

DummyPriorityThread.Sleep(<Time in Second>);

Killing Thread:
When there is a need to kill a thread use the following to achieve the same.

DummyPriorityThread.Abort();

Synchronization
There is always a requirement of Synchronization between threads. Following code give some insight of this concept.

 

using System;
using System.Threading;

namespace SynchronizationThreadsExample
{
class SynchronizationThreadsExample
{
private int counter = 0;
static void Main( )
{

        SynchronizationThreadsExample STE = new SynchronizationThreadsExample();
STE.ThreadFunction( );
}

    public void ThreadFunction ( )
{

        Thread DummyThread = new Thread( new ThreadStart(SomeFunction) ;
DummyThread.IsBackground=true;
DummyThread.Name = “First Thread”;
DummyThread.Start( );
Console.WriteLine(“Started thread {0}”, DummyThread.Name);
Thread DummyPriorityThread = new Thread( new ThreadStart(SomeFunction) );
DummyPriorityThread.IsBackground=true;
DummyPriorityThread.Name = “Second Thread”;
DummyPriorityThread.Start( );
Console.WriteLine(“Started thread {0}”, DummyPriorityThread.Name);
DummyThread.Join( );
DummyPriorityThread.Join( );
}

public void SomeFunction( )
{
try
{
while (counter < 10)
{
int tempCounter = counter;
tempCounter ++;
Thread.Sleep(1);
counter = tempCounter;
Console.WriteLine( “Thread {0}. SomeFunction: {1}”,Thread.CurrentThread.Name,
counter);
}

        }
catch (ThreadInterruptedException Ex)
{
Console.WriteLine( “Exception in thread {0} “, Thread.CurrentThread.Name);
}
finally
{
Console.WriteLine( “Thread {0} Exiting. “,Thread.CurrentThread.Name);
}

    }

}

}

Using Interlock

 

 

C# provides a special class called interlocked just for the reason of locking. We can add the following statement example for locking

Interlocked.SomeFunction (ref counter);

Using Locks: This used to lock the critical section of the code and thus help in synchronization. Locking is achieved in following way,

 

lock (this)
{
Some statements ;
}


Using Monitor
When there is a need to monitor thread we can use the following method,
Monitor.Enter(this);

 

 

There are many other methods that are very help in Thread management.

Disadvantage of Threads:

There are some disadvantages of threads also, as mentioned below

  • If you have a large number of threads, it can hurt performance, Since the OS switches between them
  • More number of threads results in more memory
  • Threads can introduce many bugs in the application so should be used carefully
  • Thread killing requires lots of post effect information to protect the application
  • Usually apartment model the data is shared across the threads, A proper locking system needs to be in place for data sharing

There are two main ways of multi-threading which .NET encourages: starting your own threads with ThreadStart delegates, and using the ThreadPool class either directly (using ThreadPool.QueueUserWorkItem) or indirectly using asynchronous methods (such as Stream.BeginRead, or calling BeginInvoke on any delegate). In general, you should create a new thread “manually” for long-running tasks, on the other hand, for short-running tasks, particularly those created often, the thread pool is an excellent choice. The thread pool can run many jobs at once, and uses framework classes internally. In case of Synchronization as there are limited amount of recourses, there can restriction on the access to the resource by one thread at a time. In this situations we can think of implementing locking on the thread. The base class used for threading is System.Threading. All the threads are managed under the Common Language Runtime.