public void Dispose() { if (TaskSlotScheduler != null) { TaskSlotScheduler.FreeSlot(); TaskSlotScheduler = null; } }
internal static async Task <BuildResult> RunParallelBuildOperation(ProgressMonitor monitor, ConfigurationSelector configuration, IEnumerable <SolutionItem> sortedItems, Func <ProgressMonitor, SolutionItem, Task <BuildResult> > buildAction, bool ignoreFailed) { List <SolutionItem> toBuild = new List <SolutionItem> (sortedItems); BuildResult cres = new BuildResult(); cres.BuildCount = 0; // Limit the number of concurrent builders to processors / 2 var slotScheduler = new TaskSlotScheduler(Environment.ProcessorCount / 2); // Create a dictionary with the status objects of all items var buildStatus = new Dictionary <SolutionItem, BuildStatus> (); foreach (var it in toBuild) { buildStatus.Add(it, new BuildStatus()); } // Start the build tasks for all itemsw foreach (var itemToBuild in toBuild) { if (monitor.CancellationToken.IsCancellationRequested) { break; } var item = itemToBuild; var myStatus = buildStatus [item]; var myMonitor = monitor.BeginAsyncStep(1); // Get a list of the status objects for all items on which this one depends var refStatus = item.GetReferencedItems(configuration).Select(it => { BuildStatus bs; buildStatus.TryGetValue(it, out bs); return(bs); }).Where(t => t != null).ToArray(); // Build the item when all its dependencies have been built var refTasks = refStatus.Select(bs => bs.Task); myStatus.Task = Task.WhenAll(refTasks).ContinueWith(async t => { if (!ignoreFailed && (refStatus.Any(bs => bs.Failed) || t.IsFaulted)) { myStatus.Failed = true; } else { using (await slotScheduler.GetTaskSlot()) myStatus.Result = await buildAction(myMonitor, item); myStatus.Failed = myStatus.Result != null && myStatus.Result.ErrorCount > 0; } myMonitor.Dispose(); }, Runtime.MainTaskScheduler).Unwrap(); if (!Runtime.Preferences.ParallelBuild.Value) { await myStatus.Task; } } // Wait for all tasks to end await Task.WhenAll(buildStatus.Values.Select(bs => bs.Task)); // Generate the errors in the order they were supposed to build foreach (var it in toBuild) { BuildStatus bs; if (buildStatus.TryGetValue(it, out bs) && bs.Result != null) { cres.Append(bs.Result); } } return(cres); }