ENTERPRISE

Programming .NET Components : Working with Threads (part 1)

12/24/2013 8:32:45 PM

1. Threads and Multithreading

In modern computing terminology, a thread is simply a path of execution within a process. Every application runs on at least one thread, which is initialized when the process within which the application runs is started up. The threads of an application always execute within the context provided by the application process. Typically, you find two kinds of operations in any application: CPU-bound and I/O-bound operations. CPU-bound operations use the machine's central processing unit (CPU) to perform intensive or repetitious computations. I/O-bound operations are tied to an input or output device such as a user-interface peripheral (keyboard, screen, mouse, or printer), a hard drive (or any non-memory durable storage), a network or communication port, or any other hardware device.

It's often useful to create multiple threads within an application, so that operations that are different in nature can be performed in parallel and the machine's CPU (or CPUs) and devices can be used as efficiently as possible. An I/O-bound operation (such as disk access), for example, can take place concurrently with a CPU-bound operation (such as the processing of an image). As long as two I/O-bound operations don't use the same I/O device (such as disk access and network-socket access), having them run on two different threads will improve your application's ability to efficiently handle these I/O devices and increase the application's throughput and performance. In the case of CPU-bound operations, on a single-CPU machine there is no performance advantage to allocating two distinct threads to run separate CPU-bound operations. However, you should definitely consider doing so on a multi-CPU machine, because multithreading is the only way to use the extra processing power available through each additional CPU.

Almost all modern applications are multithreaded, and many of the features users take for granted would not be possible otherwise. For example, a responsive user interface implies multithreading. The application processes user requests (such as printing or connecting to a remote machine) on a different thread than the one employed for the user interface. If the same thread were being used, the user interface would appear to hang while the other requests were being processed. With multithreading, because the user interface is on a different thread, it remains responsive while the user's requests are being processed. Multiple threads are also useful in applications that require high throughput. When your application needs to process incoming client requests as fast as it can, it's often advantageous to spin off a number of worker threads to handle requests in parallel.

Do not create multiple threads just for the sake of having them. You must examine your particular case carefully and evaluate all possible solutions. The decision to use multiple threads can open a Pandora's box of thread-synchronization and component-concurrency issues,.


2. Components and Threads

A component-oriented application doesn't necessarily need to be multithreaded. The way in which an application is divided into components is unrelated to how many execution threads it uses. In any given application, you're as likely to have several components interacting with one another on a single thread of execution as you are to have multiple threads accessing a single component. What is special about component-oriented applications has to do with the intricate synchronization issues inherent in the nature of component development and deployment.

3. Working with Threads

In .NET, a thread is the basic unit of execution. .NET threads are managed code representations of the underlying threads of the operating system. Under the current version of .NET on Windows, .NET threads map one-to-one to Win32 native threads. However, this mapping can be changed in other hosts. For example, SQL Server 2005 is a managed CLR host and is capable of using fibers for managed threads. The underlying host is considered to be Windows unless otherwise specified. For each thread, the operating system allocates registers, a program counter, a stack, and a stack pointer, and assigns it a time slot and a priority. The operating system (presently) is the one responsible for thread scheduling and thread context switches, as well as thread-manipulation requests such as start and sleep. .NET exposes some of the native thread properties (such as priority). It also associates various managed-code properties with each thread, such as state, exception handlers, security principal , name, unique ID, and culture (required for localization).

The .NET class Thread, defined in the System.Threading namespace, represents a managed thread. The Thread class provides various methods and properties to control the managed thread.

Calling the methods of the Thread class (be they static or instance methods) is always done on the stack of the calling thread, not on the stack of the thread represented by the Thread object. The one exception to this rule occurs when the calling thread calls methods on a Thread object that represents itself.


You can get hold of the thread on which your code is currently running by using the CurrentThread read-only static property of the Thread class:

    public sealed class Thread
{
public static Thread CurrentThread {get;}
//Other methods and properties
}

The CurrentThread property returns an instance of the Thread class. Each thread has a unique thread identification number, called a thread ID. You can access the thread ID via the ManagedThreadId property of the Thread class:

    using System.Threading;

Thread currentThread = Thread.CurrentThread;
int threadID = currentThread.ManagedThreadId;
Trace.WriteLine("Thread ID is "+ threadID);

Thread.ManagedThreadId is guaranteed to return a value that is unique process-wide. It's worth mentioning that the thread ID obtained by ManagedThreadId isn't related to the native thread ID allocated by the underlying operating system. You can verify that by opening Visual Studio's Threads debug window (Debug → Windows) during a debugging session and examining the value in the ID column (see Figure 1). The ID column reflects the physical thread ID. The ManagedThreadId property simply returns a unique hash of the thread object. Having different IDs allows .NET threads in different hosting environments (such as Windows or SQL Server 2005) to map differently to the native operating support.

Figure 1. The Threads debug window

Another useful property of the Thread class is the Name string property. Name allows you to assign a human-readable name to a thread:

    using System.Threading;

Thread currentThread = Thread.CurrentThread;
string threadName = "Main UI Thread";
currentThread.Name = threadName;

Only you as the developer can assign the thread name, and by default, a new .NET thread is nameless. You can only set the thread's name once. Although naming a thread is optional, I highly recommend doing so because it's an important productivity feature. Windows doesn't have the ability to assign a name to a thread. In the past, when you debugged native Windows code, you had to record the new thread ID in every debugging session (using the Threads debug window). These IDs were not only confusing (especially when multiple threads were involved) but also changed in each new debugging session. Visual Studio's Threads debug window (see Figure 1) displays the value of the Name property, thus easing the task of tracing and debugging multithreaded applications. You can even set a breakpoint filter, instructing the debugger to break only when a thread with a specific name hits the breakpoint. Name is a good example of a managed-code property that .NET adds to native threads.

In Visual Studio 2005, breakpoint filters are disabled by default. To enable them, go to Tools → Options → Debugging → General and check the "Enable breakpoint filters" checkbox. Now, you can set a breakpoint filter by selecting Filter...from the breakpoint context menu.


Other  
  •  System Center Configuration Manager 2007 : Integrating Virtual Applications (part 3) - Creating Adobe Reader as a Virtual Application in ConfigMgr R2
  •  System Center Configuration Manager 2007 : Integrating Virtual Applications (part 2) - Activating Application Virtualization in ConfigMgr 2007 R2
  •  System Center Configuration Manager 2007 : Integrating Virtual Applications (part 1) - What Is SoftGrid?
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Planning for Archiving (part 2)
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Planning for Archiving (part 1)
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Planning for Conferencing
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Planning for IM
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Planning for Capacity
  •  Microsoft Lync Server 2010 : Planning for Internal Non-Voice Deployment - Determining Your Infrastructure Needs
  •  Microsoft Lync Server 2010 : Determining the Scope of the Deployment
  •  
    Top 10
    Review : Sigma 24mm f/1.4 DG HSM Art
    Review : Canon EF11-24mm f/4L USM
    Review : Creative Sound Blaster Roar 2
    Review : Philips Fidelio M2L
    Review : Alienware 17 - Dell's Alienware laptops
    Review Smartwatch : Wellograph
    Review : Xiaomi Redmi 2
    Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
    Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
    3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    VIDEO TUTORIAL
    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
    Popular Tags
    Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8