Developing Multi-Threaded .NET Applications
Developing Multi-Threaded .NET Applications
Rating:
A thread is a sequence of code execution within a single process. It does not have its own address space. However, it uses the memory and other resources of the process in which it executes. A thread consists of identification, a stack, a register set containing the program or the instruction pointer, the stack pointer, and a priority. A process can have multiple threads that execute independently and concurrently with its own sequence of instructions. Therefore, multiple operations are performed concurrently within a single process and each operation is treated as a thread. Multiple operations are also referred to as multi-threaded operations.
In a multi-threaded operation, all threads in a single process exist in the same address space and share all the resources belonging to the process. A thread can create, suspend, resume, terminate, or change the priority of another thread within a single process. A thread can kill its process by canceling the main or primary thread. Therefore, canceling the main thread terminates all the threads of the process. If any changes occur to the main thread, it can also affect all the threads of the process. Even the priority of the process, when changed, can also change the priorities of all threads that inherited.
The .NET Framework supports a multi-threaded operation in developing .NET applications. Multiple threads within a single process can manage the multi-tasks of an application. As compared to multiple processes, multiple threads can increase the throughput of an application and simplify program structure. In a multi-threaded operation, the application does not require any special mechanism to communicate between its tasks, and less system resources are needed for context switching between the tasks.
Multiple threads can accomplish various tasks while working in a single application domain. They can communicate to a Web server and a database over a network. They can perform operations that are time taking and can distinguish various tasks of varying priority. Multiple threads also enable the user interface to be more responsive during the time allocation of background tasks.
However, one should avoid using multiple threads in a single application domain, as the consumption of operating-system resources can be minimized and the application performance enhanced. The frequent use of threads can cause the computer to consume more memory. There are a limited number of processes that require the context information, AppDomain objects, and threads according to the storage space in the memory. It is also very difficult to keep track of large number of threads, as it consumes significant processor time. Therefore, if there are multiple threads executing in a single process, threads in other processes get less frequent time period for execution.
Furthermore, several errors can occur in the source code while controlling code execution with large number of threads. Similarly, a large number of threads can also cause conflicts when different resources are shared among multiple threads. In order to avoid these conflicts, it is better to control access to shared resources by providing synchronization objects. By synchronization objects, one can coordinate resources that are shared among multiple threads. Therefore, the number of threads should be reduced to make it easier to synchronize resources. The resources that require synchronization can include the following:
- System resources, e.g. communication ports
- Resources that are shared by more than one process, e.g. file handles
- Resources of an application domain shared by multiple threads, e.g. global, static, and instance fields
The .NET Framework provides the
| Abort | Raises a ThreadAbortException exception on the thread that is being invoked and begins the process of the thread's termination. |
| Interrupt | Raises a ThreadInterruptedException exception when a thread is interrupted or when the thread is in a blocked state, i.e. in a wait, sleep, or join state. |
| Join | Blocks the thread that is recently being called until the previous thread terminates. |
| Start | Sets a thread to execute. |
| Sleep | Blocks the current thread for a specified time period (in milliseconds). Allows the execution of other threads. |
| SpinWait | Blocks the current thread for a certain number of iterations. Does not allow the execution of other threads. |
Some of the major properties of the Thread class are as follows:
| IsAlive | Returns a value of the current thread that is recently executing. |
| IsBackground | Gets a value to indicate whether or not the thread is running as a background thread. |
| IsThreadPoolThread | Gets a value to indicate whether or not a thread belongs to the thread pool. |
| ManagedThreadId | Returns a unique identifier to identify the currently managed thread. |
| Name | Returns a string that contains the name of the thread. |
| Priority | Returns a value to indicate the thread's priority. The default property value is Normal. |
| ThreadState | Gets a value to indicate the state of the current thread. |
The following code snippet displays a simple multi-threaded processing in a process:
using System.Threading;
public class ThreadProcess1
{
public static void Thread1()
{
Console.Write("Enter your first name");
string fname = Console.ReadLine();
Console.WriteLine("The length of your first name is: {0}", fname.Length);
Thread.Sleep(0);
}
public static void Thread2()
{
Console.Write("Enter your last name");
string lname = Console.ReadLine();
Console.WriteLine("The length of your last name is: {0}", lname.Length);
Thread.Sleep(0);
}
public static void Main()
{
Console.WriteLine("Start a thread.");
Thread t1 = new Thread(new ThreadStart(Thread1));
t1.Start();
Thread.Sleep(0);
Console.WriteLine("Wait until the first task ends.");
t1.Join();
Console.WriteLine("Start another thread.");
Thread t2 = new Thread(new ThreadStart(Thread2));
t2.Start();
Thread.Sleep(0);
t2.Join();
Console.WriteLine("Press Enter to end program.");
Console.ReadLine();
}
}
The .NET Framework provides a class known as the
Since the Windows operating system is designed to optimize the scheduling of threads, a developer can adjust a thread's scheduling priority in order to reduce bottlenecks and allow blocked threads to run. A thread determines its priority property to determine the manner in which the time can slice its processor time for its execution. The ability of the operating system is to allocate longer time slices to those threads that have high priority properties and shorter time slices to threads with low priority properties. In .NET infrastructure, the
- Highest
- AboveNormal
- Normal
- BelowNormal
- Lowest
A thread in a thread pool can be in any one of the states of execution. The
| Aborted | Specifies the thread to be in the Stopped state. |
| AbortRequested | Requests the thread to be aborted. But the thread has not yet received the ThreadAbortException exception that causes the thread to terminate. |
| Background | Specifies the execution of a thread as a background thread. |
| Running | Indicates that the thread has been started and it is not blocked. |
| Stopped | Indicates that the thread has been stopped. |
| StopRequested | Requests the thread to stop. |
| Suspended | Indicates that the thread has been suspended. |
| SuspendRequested | Requests the thread to suspend. |
| Unstarted | Indicates that the thread has been created, but the Thread.Start method has not been called on the thread. |
| WaitSleepJoin | Indicates that the thread is blocked, as the Monitor.Wait, Thread.Sleep, or Thread.Join method is called each on separate threads. |
The .NET Framework provides a property in the Thread class known as the ThreadState property that retrieves one of the values indicating the state of the current thread in a process. The state of a current thread can be illustrated in the figure given below:

Thread synchronization is a process through which multiple threads share access to common resources. In a .NET multi-threaded application, individual threads sometimes need to be synchronized with other parts of the application program. For example, if multiple threads access the same resources for both read and write operations, the resultant value can be incorrect. If a thread writes the contents to a file and another thread reads the contents from the same file at the same time, data can become corrupted. In such a situation, the file access needs to be locked, until at least one thread completes its execution before letting the other thread to start its execution.
The Microsoft .NET Framework has provided many thread synchronization objects. One such thread synchronization object is
In a .NET application, the synchronization technique is used to control the order in which the lines of program code run when a set of tasks are to be performed in a specific sequence. The technique can also be used to prevent the problems that can arise when two or more threads share the same resources at the same time.
Rating:
Other articles
- What are the building blocks of .NET Framework?
- What are the two faces of unmanaged code?
- What is the MemoryStream class?
- What are the differences between the IComparer and IEqualityComparer interfaces?
- What is the Data Encryption Standard (DES)?
