CHAPTER 17 PROCESSES, APPDOMAINS, AND OBJECT CONTEXTS
performing a mathematically intensive calculation, or attempting to connect to a remote server located
thousands of miles away).
Given this potential drawback of single-threaded applications, the Windows API (as well as the .NET
platform) makes it possible for the primary thread to spawn additional secondary threads (also termed
worker threads) using a handful of Windows API functions such as CreateThread(). Each thread (primary
or secondary) becomes a unique path of execution in the process and has concurrent access to all shared
points of data within the process.
As you might have guessed, developers typically create additional threads to help improve the
program’s overall responsiveness. Multithreaded processes provide the illusion that numerous activities
are happening at more or less the same time. For example, an application may spawn a worker thread to
perform a labor-intensive unit of work (again, such as printing a large text file). As this secondary thread
is churning away, the main thread is still responsive to user input, which gives the entire process the
potential of delivering greater performance. However, this may not actually be the case: using too many
threads in a single process can actually degrade performance, as the CPU must switch between the active
threads in the process (which takes time).
On some machines, multithreading is most commonly an illusion provided by the OS. Machines
that host a single (non-hyperthreaded) CPU do not have the ability to literally handle multiple threads at
the same exact time. Rather, a single CPU will execute one thread for a unit of time (called a time slice)
based in part on the thread’s priority level. When a thread’s time slice is up, the existing thread is
suspended to allow another thread to perform its business. For a thread to remember what was
happening before it was kicked out of the way, each thread is given the ability to write to Thread Local
Storage (TLS) and is provided with a separate call stack, as illustrated in Figure 17-2.
Figure 17-2. The Windows process/thread relationship
If the subject of threads is new to you, don’t sweat the details. At this point, just remember that a
thread is a unique path of execution within a Windows process. Every process has a primary thread
(created via the executable’s entry point) and may contain additional threads that have been
programmatically created.
Interacting with Processes Under the .NET Platform
Although processes and threads are nothing new, the manner in which you interact with these primitives under the .NET platform has changed quite a bit (for the better). To pave the way to
understanding the world of building multithreaded assemblies (see Chapter 19), let’s begin by checking
out how to interact with processes using the .NET base class libraries.
The System.Diagnostics namespace defines a number of types that allow you to programmatically
interact with processes and various diagnostic-related types such as the system event log and
625