The
.NET Framework 4.0 provides support for parallel computing through the
Task Parallel Library (also referred to as TPL), which is a set of APIs
offered by specific extensions of the System.Threading.dll assembly.
The reference to this assembly is included by default when creating new
projects, so you do not need to add one manually. The TPL is reachable
via the System.Threading and System.Threading.Tasks,
namespaces that provide objects for scaling work execution over
multiple processors. Basically you write small units of work known as
tasks. Tasks are scheduled for execution by the TPL’s Task Scheduler,
which is responsible for executing tasks according to available
threads. This is possible because the Task Scheduler is integrated with
the .NET Thread Pool. The good news is that the .NET Framework can
automatically take advantage of all available processors on the target
machines without the need to recompile code.
Note
Parallel computing makes it to
easier to scale applications over multiple processors, but it remains
something complex in terms of concepts. This is because you will face
again some threading concepts, such as synchronization locks,
deadlocks, and so on. The suggestion is to have at least a basic
knowledge of threading issues before writing parallel code. Another
important consideration is when should you use parallel computing? The
answer is not easy because you are the only one who knows how your
applications consume resources. The general rule is that parallel
computing gives the best results when you have intensive processing
scenarios. In simpler elaborations, parallel computing is not
necessarily the best choice and can cause performance loss. Use it when
your applications require hard CPU loops.
Most of the parallel API are available through the System.Threading.Tasks.Task and System.Threading.Tasks.Parallel
classes. The first one is described in detail later, whereas we now
provide coverage of the most important classes for parallelism.
Introducing Parallel Classes
Parallelism in the .NET
Framework 4.0 is possible due to a number of classes, some responsible
for maintaining the architecture of the TPL and some for performing
operations in a concurrent fashion. The following subsection provides a
brief coverage of the most important classes, describing their purpose.
The Parallel Class
The System.Threading.Tasks.Parallel
class is one of the most important classes in parallel computing,
because it provides shared methods for running concurrent tasks and for
executing parallel loops. In this chapter you can find several examples
of usage of this class; for now you just need to know that it provides
the Invoke, For, and ForEach
shared methods. The first one enables running multiple tasks
concurrently, whereas the other ones enable executing loops in parallel.
The TaskScheduler Class
The System.Threading.Tasks.TaskScheduler
class is responsible for the low-level work of sending tasks to the
thread queue. This means that when you start a new concurrent task, the
task is sent to the scheduler that checks for thread availability in
the .NET thread pool. If a thread is available, the task is pushed into
the thread and executed. Generally you do not interact with the task
scheduler. (The class exposes some members that you can use to
understand the tasks state.) The first property is Current,
which retrieves the instance of the running task scheduler. This is
required to access information. For example, you can understand the
concurrency level by reading the MaximumConcurrencyLevel property as follows:
Console.WriteLine("The maximum concurrency level is {0}",
TaskScheduler.Current.MaximumConcurrencyLevel)
There are also some protected methods that can be used to force tasks’ execution (such as QueueTask and TryDequeue) but these are accessible if you want to create your custom task scheduler, which is beyond of the scope in this chapter.
The TaskFactory Class
The System.Threading.Tasks.TaskFactory class provides support for generating and running new tasks and is generally exposed as a shared property of the TaskStartNew method, which enables creating a new task and automatically starting it. class, as explained in the next section about tasks. The most important member is the
The ParallelOptions Class
The System.Threading.Tasks.ParallelOptions
class provides a way for setting options on tasks’ creation.
Specifically it provides properties for setting tasks’ cancellation
properties (CancellationToken), the instance of the scheduler (TaskScheduler), and the maximum number of threads that a task is split across (MaxDegreeOfParallelism).