Parallel’s Static For, ForEach, and Invoke Methods

  1. When is better to use Parallel.For, Parallel.ForEach
    and Parallel.Invoke methods?
  2. How do Parallels methods
    work?
  3. What are overloads of
    the Parallel.For and Parallel.ForEach methods?

We don’t have to use parallels methods when operations must be processed
in sequential order. To gain a performance increase we should use parallels
methods when we have many work items which can be processed by multiple threads
(they don’t have shared data) or long-running compute-bound operations.

Sample 1

int n = 20;

int[] array = new int[20] { 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };

Parallel.For(0, n,
i => DoWork(i));

Parallel.ForEach(array,
i => DoWork(i));

The calling thread also participate in processing work items however if it
completes its processing before the thread pool threads will finish their work the
calling thread suspends itself until all the work is done.

Sample 2

CancellationTokenSource cts = new CancellationTokenSource();

ParallelOptions opts = new ParallelOptions

{

CancellationToken = cts.Token

,

MaxDegreeOfParallelism = -1

,

TaskScheduler = TaskScheduler.Default

};

Parallel.Invoke(opts,
new Action[]{

() => { Thread.Sleep(400);
Console.WriteLine(“call
1”); }

, () => { Thread.Sleep(300);
Console.WriteLine(“call
2”);  }

, () => { Thread.Sleep(200);
Console.WriteLine(“call
3”);  }

, () => { Thread.Sleep(100);
Console.WriteLine(“call
4”);  }

});

Name Description
CancellationToken Gets or
sets the CancellationToken
associated with this ParallelOptions instance.
MaxDegreeOfParallelism Gets or
sets the maximum degree of parallelism enabled by this ParallelOptions
instance.
TaskScheduler Gets or
sets the TaskScheduler
associated with this ParallelOptions instance.Setting
this property to null indicates that the current scheduler should be used

There are overloads methods
for Parallel.ForEach and Parallel.For which allow controlling execution.

localInit

Type: System.Func<TLocal>

The function delegate that returns the initial
state of the local data for each thread.

The state
that is returned from the localInit method can be passed to the first body invocation
for each thread.

body

Type: System.Func<Int32, ParallelLoopState, TLocal, TLocal>

The delegate that is invoked once per iteration.

The
result that is returned from the body can be passed to be processed by the
localFinally delegate.

localFinally

Type: System.Action<TLocal>

The delegate that performs a final action on the
local state of each thread.

Sample 3

private static void
ParralelForWithInitBodyFinal()

{

long
totalLength = 0;

try

{

ParallelLoopResult
result = Parallel.ForEach<string, long>(

Directory.GetFiles(@”C:\rush\”)

, () =>
{ Console.WriteLine(“Local
task init”); return 0; }

, (path2file, loopState, index,
runningTotal) =>

{

Console.WriteLine(“Is exceptional: {0}”,
loopState.IsExceptional);

long
fileLength = 0;

using
(FileStream fs = new
FileStream(path2file, FileMode.Open))

{

fileLength = fs.Length;

}

return
runningTotal += fileLength;

}

, runningTotal =>

{

Console.WriteLine(“Local task finally”);

Interlocked.Add(ref totalLength, runningTotal);

});

Console.WriteLine(result.ToString());

}

catch (AggregateException ex)

{

foreach
(Exception innerException in ex.InnerExceptions)

{

Console.WriteLine(innerException);

}

}

Console.WriteLine(totalLength);

}

We can
manage execution of the Parallel.For and Parallel.ForEach methods using ParallelLoopState members.

Methods

Name Description
Break Communicates
that the Parallel loop should cease execution at the
system’s earliest convenience of iterations beyond the current iteration.
Stop Communicates
that the Parallel loop should cease execution at the
system’s earliest convenience.

Properties

Name Description
IsExceptional Gets
whether any iteration of the loop has thrown an exception that went unhandled
by that iteration.
IsStopped Gets
whether any iteration of the loop has called Stop.
LowestBreakIteration Gets
the lowest iteration of the loop from which Break was called.
ShouldExitCurrentIteration Gets
whether the current iteration of the loop should exit based on requests made
by this or other iterations.

The ParallelLoopResult has
following properties:

Name Description
IsCompleted Gets
whether the loop ran to completion, such that all iterations of the loop were
executed and the loop didn’t receive a request to end prematurely.
LowestBreakIteration Gets
the index of the lowest iteration from which Break was
called.