Threads are units of work that are created by a parent process to perform some task. By utilizing multiple threads, an application can delegate the work to multiple workers to reduce the time it takes to complete a relatively long task.
In addition, a background task can be used to perform some long-running or expensive processing in the background while the foreground remains responsive. This allows web applications to process extremely lengthy requests while not blocking out small, lightweight requests in the meantime. It also allows the user interface in a Windows Forms application to remain responsive while large amounts of data are downloaded or processed in the background. Threading has a virtually unlimited number of applications.
However, using threads just because you think they will make your application run faster can often backfire. In fact, using too many threads can actually cause your application to run slower. For example, you could have so many threads running that your application is spending more time swapping context between the threads than it is performing the tasks within the threads. In this case, your application will actually run slower than if it had no threading support whatsoever.
No matter what task you're performing in a multithreaded environment, you will be working with the Thread class in one form or another. Tables 10.1 and 10.2 show some of the commonly used methods and properties of the Thread class.
Table 10.1. Thread Properties
Indicates the Apartment State of the thread. Can be MTA (Multithreaded Apartment), STA (Single-Threaded Apartment), or Unknown (not set).
Static property that obtains the current threading context in which the thread is running.
The current culture for the thread. This becomes important when creating localized/globalized applications.
The user security context that owns/created the current thread.
Indicates whether the thread is currently active.
Indicates whether the thread is a background thread. Active background threads cannot prevent an application from terminating but foreground threads can.
Indicates whether the thread belongs to the thread pool. The thread pool will be discussed later in this chapter, in the section "Using the THReadpool Class."
A unique identifier for this thread.
Gets or sets the name of the thread. Useful for distinguishing one thread from another without relying on thread IDs.
Indicates the thread's priority with regard to the execution scheduler. Values can be AboveNormal, BelowNormal, Highest, Lowest, and Normal. Default is normal.
Indicates the current state of the thread. Can be Aborted, AbortRequested, Background, Running, Stopped, StopRequested, Suspended, SuspendRequested, Unstarted, or WaitSleepJoin (blocked).
Table 10.2. Thread Methods
Aborts the current thread, requesting that all active work be stopped
Static method that allocates an unnamed slot for storing data shared among all threads
Static method that creates a named data slot shared among all threads
Indicates that the following section of code is "critical," meaning aborts and unhandled exceptions could put the code in an unstable state
Indicates that the preceding section of code is to be treated as "critical"
Removes the space previously allocated for a named thread-shared data slot
Retrieves the data stored in a thread-local data slot
Returns the currently active thread domain
Returns a thread-shared named data slot
Interrupts the current thread if it is blocked
Blocks the current thread until another thread completes (explained later in the section "Joining a Thread")
Resumes the previously suspended thread
Sets data stored in a thread-local data slot
Causes the thread to block and wait for the specified number of milliseconds
Indicates to the scheduler that the thread is ready for execution
Don't worry if some of the properties or methods of the THRead class don't make much sense yet. By the time you've finished this chapter, it should all be clear.
Essentially, two main concepts are involved in creating any good multithreaded application:
Thread scheduling You will need to know how to start, stop, suspend, pause, and terminate threads in your applications.
Thread contention With multiple threads running at the same time, you will need to learn the techniques required to ensure that you don't have multiple threads modifying the same piece of data at the same time, or that you end up with incomplete modifications of shared data.