C H A P T E R 19
Multithreaded, Parallel, and Async
Programming
Nobody enjoys working with an application that is slow and sluggish during its execution. Moreover,
nobody enjoys starting a task in an application (perhaps initiated by the clicking of a toolbar item) that
prevents other parts of the program from being as responsive as possible. Before the release of .NET,
building applications that had the ability to perform multiple tasks required authoring very complex C++
code that made use of the Windows threading APIs. Thankfully, the .NET platform provides a number of
ways for you to build software that can perform complex operations on unique paths of execution, with
far fewer pain points.
This chapter begins by defining the overall nature of a “multithreaded application.” Next, we will
revisit the .NET delegate type to investigate its intrinsic support for asynchronous method invocations. As
you’ll see, this technique allows you to invoke a method on a secondary thread of execution without
needing to manually create or configure the thread itself.
Next, you’ll be introduced to the original threading namespace which has shipped since .NET 1.0,
specifically System.Threading. Here you’ll examine numerous types (Thread, ThreadStart, etc.) that allow
you to explicitly create additional threads of execution and synchronize your shared resources, which
helps ensure that multiple threads can share data in a nonvolatile manner.
The remaining parts of this chapter will examine three more recent techniques .NET developers can
make use of to build multithreaded software, specifically the Task Parallel Library (TPL), Parallel LINQ
(PLINQ), and the new intrinsic asynchronous keywords of C# (async and await). As you will see, these
features can dramatically simplify how you can build responsive multithreaded software applications.
The Process/AppDomain/Context/Thread Relationship
In Chapter 17, a thread was defined as a path of execution within an executable application. While many
.NET applications can live happy and productive single-threaded lives, an assembly’s primary thread
(spawned by the CLR when Main() executes) may create secondary threads of execution at any time to
perform additional units of work. By creating additional threads, you can build more responsive (but not
necessarily faster executing on single-core machines) applications.
The System.Threading namespace was released with .NET 1.0, and offers one approach to build
multithreaded applications. The Thread class is perhaps the core type, as it represents a given thread. If
you want to programmatically obtain a reference to the thread currently executing a given member,
simply call the static Thread.CurrentThread property, like so:
static void ExtractExecutingThread()
{
// Get the thread currently
// executing this method.
697