Beispiel #1
0
 public void Dispose()
 {
     if (TaskSlotScheduler != null)
     {
         TaskSlotScheduler.FreeSlot();
         TaskSlotScheduler = null;
     }
 }
Beispiel #2
0
        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);
        }