1.Parallel类 invoke方法
// System.Threading.Tasks.Parallel
// Token: 0x06003EDA RID: 16090 RVA: 0x000E9630 File Offset: 0x000E7830
[__DynamicallyInvokable]
public static void Invoke(ParallelOptions parallelOptions, params Action[] actions)
{
if (actions == null)
{
throw new ArgumentNullException("actions");
}
if (parallelOptions == null)
{
throw new ArgumentNullException("parallelOptions");
}
if (parallelOptions.CancellationToken.CanBeCanceled && AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
{
parallelOptions.CancellationToken.ThrowIfSourceDisposed();
}
if (parallelOptions.CancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(parallelOptions.CancellationToken);
}
Action[] actionsCopy = new Action[actions.Length];
for (int i = 0; i < actionsCopy.Length; i++)
{
actionsCopy[i] = actions[i];
if (actionsCopy[i] == null)
{
throw new ArgumentException(Environment.GetResourceString("Parallel_Invoke_ActionNull"));
}
}
int forkJoinContextID = 0;
Task task = null;
if (TplEtwProvider.Log.IsEnabled())
{
forkJoinContextID = Interlocked.Increment(ref Parallel.s_forkJoinContextID);
task = Task.InternalCurrent;
TplEtwProvider.Log.ParallelInvokeBegin((task != null) ? task.m_taskScheduler.Id : TaskScheduler.Current.Id, (task != null) ? task.Id : 0, forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelInvoke, actionsCopy.Length);
}
if (actionsCopy.Length < 1)
{
return;
}
try
{
if (actionsCopy.Length > 10 || (parallelOptions.MaxDegreeOfParallelism != -1 && parallelOptions.MaxDegreeOfParallelism < actionsCopy.Length))
{
ConcurrentQueue<Exception> exceptionQ = null;
try
{
int actionIndex = 0;
ParallelForReplicatingTask parallelForReplicatingTask = new ParallelForReplicatingTask(parallelOptions, delegate()
{
for (int l = Interlocked.Increment(ref actionIndex); l <= actionsCopy.Length; l = Interlocked.Increment(ref actionIndex))
{
try
{
actionsCopy[l - 1]();
}
catch (Exception item2)
{
LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => new ConcurrentQueue<Exception>());
exceptionQ.Enqueue(item2);
}
if (parallelOptions.CancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(parallelOptions.CancellationToken);
}
}
}, TaskCreationOptions.None, InternalTaskOptions.SelfReplicating);
parallelForReplicatingTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler);
parallelForReplicatingTask.Wait();
}
catch (Exception ex)
{
LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => new ConcurrentQueue<Exception>());
AggregateException ex2 = ex as AggregateException;
if (ex2 != null)
{
using (IEnumerator<Exception> enumerator = ex2.InnerExceptions.GetEnumerator())
{
while (enumerator.MoveNext())
{
Exception item = enumerator.Current;
exceptionQ.Enqueue(item);
}
goto IL_277;
}
}
exceptionQ.Enqueue(ex);
IL_277:;
}
if (exceptionQ != null && exceptionQ.Count > 0)
{
Parallel.ThrowIfReducableToSingleOCE(exceptionQ, parallelOptions.CancellationToken);
throw new AggregateException(exceptionQ);
}
}
else
{
Task[] array = new Task[actionsCopy.Length];
if (parallelOptions.CancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(parallelOptions.CancellationToken);
}
for (int j = 1; j < array.Length; j++)
{
array[j] = Task.Factory.StartNew(actionsCopy[j], parallelOptions.CancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, parallelOptions.EffectiveTaskScheduler);
}
array[0] = new Task(actionsCopy[0]);
array[0].RunSynchronously(parallelOptions.EffectiveTaskScheduler);
try
{
if (array.Length <= 4)
{
Task.FastWaitAll(array);
}
else
{
Task.WaitAll(array);
}
}
catch (AggregateException ex3)
{
Parallel.ThrowIfReducableToSingleOCE(ex3.InnerExceptions, parallelOptions.CancellationToken);
throw;
}
finally
{
for (int k = 0; k < array.Length; k++)
{
if (array[k].IsCompleted)
{
array[k].Dispose();
}
}
}
}
}
finally
{
if (TplEtwProvider.Log.IsEnabled())
{
TplEtwProvider.Log.ParallelInvokeEnd((task != null) ? task.m_taskScheduler.Id : TaskScheduler.Current.Id, (task != null) ? task.Id : 0, forkJoinContextID);
}
}
}