Click or drag to resize
DigitalRuneParallel Class
Provides support for parallel execution of tasks.
Inheritance Hierarchy
SystemObject
  DigitalRune.ThreadingParallel

Namespace: DigitalRune.Threading
Assembly: DigitalRune (in DigitalRune.dll) Version: 1.20.0.0 (1.20.1.14552)
Syntax
public static class Parallel

The Parallel type exposes the following members.

Methods
  NameDescription
Public methodStatic memberDo(Action)
Executes the given work items potentially in parallel with each other. This method will block until all work is completed.
Public methodStatic memberDo(IWork)
Executes the given work items potentially in parallel with each other. This method will block until all work is completed.
Public methodStatic memberDo(Action, Action)
Executes the given work items potentially in parallel with each other. This method will block until all work is completed.
Public methodStatic memberDo(IWork, IWork)
Executes the given work items potentially in parallel with each other. This method will block until all work is completed.
Public methodStatic memberFor(Int32, Int32, ActionInt32)
Executes a for loop where each iteration can potentially occur in parallel with others.
Public methodStatic memberFor(Int32, Int32, ActionInt32, Int32)
Executes a for loop where each iteration can potentially occur in parallel with others.
Public methodStatic memberForEachT
Executes a for-each loop where each iteration can potentially occur in parallel with others.
Public methodStatic memberRunCallbacks
Executes all task callbacks on a single thread.
Public methodStatic memberStart(Action)
Creates and starts a task to execute the given work.
Public methodStatic memberStart(IWork)
Creates and starts a task to execute the given work.
Public methodStatic memberStart(Action, WorkOptions)
Creates and starts a task to execute the given work.
Public methodStatic memberStart(Action, Action)
Creates and starts a task to execute the given work.
Public methodStatic memberStart(IWork, Action)
Creates and starts a task to execute the given work.
Public methodStatic memberStart(Action, WorkOptions, Action)
Creates and starts a task to execute the given work.
Public methodStatic memberStartT(FuncT)
Creates and starts a task which executes the given function and stores the result for later retrieval.
Public methodStatic memberStartT(FuncT, WorkOptions)
Creates an starts a task which executes the given function and stores the result for later retrieval.
Public methodStatic memberStartT(FuncT, Action)
Creates and starts a task which executes the given function and stores the result for later retrieval.
Public methodStatic memberStartT(FuncT, WorkOptions, Action)
Creates and starts a task which executes the given function and stores the result for later retrieval.
Public methodStatic memberStartBackground(Action)
Starts a task in a secondary worker thread. Intended for long running, blocking work such as I/O.
Public methodStatic memberStartBackground(IWork)
Starts a task in a secondary worker thread. Intended for long running, blocking work such as I/O.
Public methodStatic memberStartBackground(Action, Action)
Starts a task in a secondary worker thread. Intended for long running, blocking, work such as I/O.
Public methodStatic memberStartBackground(IWork, Action)
Starts a task in a secondary worker thread. Intended for long running, blocking work such as I/O.
Top
Properties
  NameDescription
Public propertyStatic memberProcessorAffinity
Gets or sets the processor affinity of the worker threads.
Public propertyStatic memberScheduler
Gets or sets the task scheduler.
Top
Remarks

The namespace DigitalRune.Threading and the class Parallel provides support for concurrency to run multiple tasks in parallel and automatically balance work across all available processors. The implementation is a replacement for Microsoft's Task Parallel Library (see Task Parallelism (Task Parallel Library)) which is not yet supported by the .NET Compact Framework. This class Parallel provides a lightweight and cross-platform implementation (supported on Windows, Silverlight, Windows Phone 7, and Xbox 360).

The API has similarities to Microsoft's Task Parallel Library, but it is not identical. The names in the namespace DigitalRune.Threading conflict with the types of the namespace System.Threading.Tasks. This is on purpose as only one solution for concurrency should be used in an application. The library has been optimized for the .NET Compact Framework: Only the absolute minimum of memory is allocated at runtime.

The DigitalRune libraries, such as DigitalRune Geometry and DigitalRune Physics, /// make extensive use of the class Parallel. We highly recommend, that if you need support for multithreading in your application, you should take advantage of this class. (Using different solutions for concurrency can reduce performance.)

Tasks:
A task is an asynchronous operation which is started, for example, by calling Start(Action). This method returns a handle of type Task. This handle can be used to query the status of the asynchronous operation (see IsComplete). The method Wait can be called to wait until the operation has completed.

Futures (Task<T>):
A future is an asynchronous operation that returns a value. A future is created, for example, by calling StartT(FuncT) and specifying a function that computes a value. The method returns a handle of type TaskT, which is similar to Task. The result of a future can be queried by calling GetResult. Note that GetResult can only be called once - the handle becomes invalid after the first call!

Background Tasks:
Long running operations which may block (i.e. wait for I/O operation to finish) should be scheduled as background tasks. Background tasks are created by using the method StartBackground(Action) (or one of its overloads). Background tasks will not be scheduled using the Scheduler (see below). Instead the class Parallel manages an additional pool of threads that are used for background tasks. The processor affinity of these threads is not set automatically. The background tasks will usually run on the same hardware thread where the background thread was created first or run last. The processor affinity can be set manually from within the task by calling Thread.SetProcessorAffinity.

Exception Handling:
The tasks executed asynchronously can raise exceptions. The exceptions are stored internally and a TaskException containing these exceptions is thrown when Wait is called.

Completion Callbacks:
It is possible to specify a completion callbacks when starting a new tasks. For example, see method Start(Action, Action). The completion callbacks are executed after the corresponding tasks have completed. Completion callbacks are executed regardless of whether tasks have completed successfully or have thrown an exception.

However, the callbacks are not executed immediately! Instead, the method RunCallbacks needs to be called manually - usually on the main thread - to invoke the callbacks.

Task Scheduling:
The number of threads used for parallelization is determined by the task scheduler (see Scheduler). The task scheduler creates a number of threads and distributes the tasks among these worker threads. The default task scheduler is a WorkStealingScheduler that creates one thread per CPU core on Windows and 3 threads on Xbox 360 (on the hardware threads 3, 4, and 5). The number of worker threads can be specified in the constructor of the WorkStealingScheduler.

The property Scheduler can be changed at runtime. The default task scheduler can be replaced with another task scheduler (e.g. with a WorkStealingScheduler that uses a different number of tasks, or with a custom ITaskScheduler). Replacing a task scheduler will affect all future tasks that have not yet been scheduled. However, it is highly recommended to use the default scheduler or specify the scheduler only once at the startup of the application.

Processor Affinity:
In the .NET Compact Framework for Xbox 360 the processor affinity determines the processors on which a thread runs. Setting the processor affinity in Windows has no effect.

The processor affinity is defined as an array using the property ProcessorAffinity. Each entry in the array specifies the hardware thread that the corresponding worker thread will use. The default value is { 3, 4, 5, 1 }. The default task scheduler reads this array and assigns the worker threads to the specified hardware threads. (See also Thread.SetProcessorAffinity in the MSDN Library to find out more.)

Important: The processor affinity needs to be set before any parallel tasks are created or before a new WorkStealingScheduler is created. Changing the processor affinity afterwards has no effect.

Examples
The following example demonstrates how to configure Parallel to schedule tasks only on the hardware threads 3 and 4 of the Xbox 360.
C#
// Configure the class Parallel to use the hardware threads 3 and 4 on the Xbox 360.
// (Note: Setting the processor affinity has no effect on Windows.)
Parallel.ProcessorAffinity = new[] { 3, 4 };

// Create task scheduler that uses 2 worker threads.
Parallel.Scheduler = new WorkStealingScheduler(2);

// Note: Above code is usually run at the start of an application. It is not recommended to 
// change the processor affinity or the task scheduler at runtime of the application.

The following example demonstrates how a task is started.

C#
// Start a method call on another thread:
// DoSomeWork can either be an Action delegate, or an object which implements IWork.
Task task = Parallel.Start(DoSomeWork);

// Do something else on this thread for a while.
DoSomethingElse();

// Wait for the task to complete. This ensures that after this call returns, the task has 
//finished.
task.Wait();

The following example demonstrates how task can be used to compute values in parallel and return the result when needed.

C#
// Task<T> is similar to Task, but you can retrieve a result from it.
Task<double> piTask = Parallel.Start(CalculatePi);

// Do something else for a while.
DoSomethingElse();

// Retrieve the result. The caller will block until the task has completed. 
// GetResult() can only be called once!
double pi = piTask.GetResult();

The following example demonstrates how to run a long task in the background to avoid that the current thread is blocked.

C#
// Begin loading some files.
Parallel.StartBackground(LoadFiles);

The following demonstrates how a for-loop can be executed in parallel.

C#
// Sequential loop:
for (int i = 0; i < count; i++)
{
  DoWork(i);
}

// Same loop, but each iteration may happen in parallel on multiple threads.
Parallel.For(0, count, i =>
{
  DoWork(i);
});

The following demonstrates how a foreach-loop can be executed in parallel.

C#
// Sequential loop:
foreach (var item in list)
{
  DoWork(item);
}

// Same loop, but each iteration may happen in parallel on multiple threads.
Parallel.ForEach(list, item =>
{
  DoWork(item);
});
See Also