File: src\Compilers\Core\Portable\InternalUtilities\RoslynParallel.cs
Web Access
Project: src\src\Workspaces\Core\MSBuild.BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj (Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
 
namespace Roslyn.Utilities
{
    internal static class RoslynParallel
    {
        internal static readonly ParallelOptions DefaultParallelOptions = new ParallelOptions();
 
        /// <inheritdoc cref="Parallel.For(int, int, ParallelOptions, Action{int})"/>
        public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body, CancellationToken cancellationToken)
        {
            var parallelOptions = cancellationToken.CanBeCanceled
                ? new ParallelOptions { CancellationToken = cancellationToken }
                : DefaultParallelOptions;
 
            return Parallel.For(fromInclusive, toExclusive, parallelOptions, errorHandlingBody);
 
            // Local function
            void errorHandlingBody(int i)
            {
                try
                {
                    body(i);
                }
                catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
                {
                    throw ExceptionUtilities.Unreachable();
                }
                catch (OperationCanceledException e) when (cancellationToken.IsCancellationRequested && e.CancellationToken != cancellationToken)
                {
                    // Parallel.For checks for a specific cancellation token, so make sure we throw with the
                    // correct one.
                    cancellationToken.ThrowIfCancellationRequested();
                    throw ExceptionUtilities.Unreachable();
                }
            }
        }
    }
}