Thread-Local Variables

Stores and retrieves state in each separate task that is created by a Parallel.For loop. Instead of writing to a shared resource on each iteration, you compute and store the value until all iterations for the task are complete.

Parallel.For w/Thread-Local Variables

Example

int[] nums = Enumerable.Range(0, 1_000_000).ToArray();
long total = 0;

Parallel.For<long>( // By default, the type parameter would be int, so this makes it `long`
    0, // Starting element index
    nums.Length, // Ending element index
    () => 0, // Initialize a thread-local variable to 0. Variable is of type `long`.
    ( // The logic loop of type `Func<Int, ParallelLoopState, long, long>` as a delegate or lambda.
        j, // Loop counter for current iteration
        loop, // a ParallelLoopState object (provided by TPL) that can be used to break out of the loop
        subtotal // a thread-local variable (provided by the runtime)
    ) =>
    {
        subtotal + nums[j]
        return subtotal;
    },
    (x) => Interlocked.Add(ref total, x);
);

Partition-Local Variables

Similar to a thread-local variable except that multiple partitions can run on a single thread and is created by a Parallel.ForEach loop.

Example

int[] nums = Enumerable.Range(0, 1_000_000).ToArray();
long total = 0;

Parallel.ForEach<int, long>( // int = type of source elements, long = type of thread-local variable
    nums, // source collection
    () => 0, // initialize a thread-local variable (of type long) to 0
    (j, loop, subtotal) => // the logic loop (explained above)
    {
        subttoal += j; // modify the local variable
        return subtotal; // value to be passed to next iteration
    },
    (finalResult) => // the final value of subtotal for a particular partition
        Interlocked.Add(ref total, finalResult) // method to execute when each partition completes
);