public void RunActionsParallel(int maxConcurrentRunners, IEnumerable<TestRunAction> buildSortedAllActions, CancellationToken token, TextWriterWrapper stdOut, ProgressStats runningTests, Stopwatch totalRuntime, ConcurrentBag<RunStats> testResults) { var sortedAllActions = buildSortedAllActions as TestRunAction[] ?? buildSortedAllActions.ToArray(); if (maxConcurrentRunners <= 0) { maxConcurrentRunners = 12; } //Waiting for complete for (var i = 0; i < sortedAllActions.Count(); i++) { token.ThrowIfCancellationRequested(); CreateThread(sortedAllActions[i], token, stdOut, runningTests, totalRuntime, testResults); //Stop queueing items once reach the limit... really should just always set this to the ThreadPool size... while (_threadCounter >= maxConcurrentRunners) Thread.Sleep(500); } while (_threadCounter > 0) Thread.Sleep(500); }
public void RunActionsParallel(int maxConcurrentRunners, IEnumerable<TestRunAction> buildSortedAllActions, CancellationToken token, TextWriterWrapper stdOut, ProgressStats runningTests, Stopwatch totalRuntime, ConcurrentBag<RunStats> testResults) { var options = new ParallelOptions { MaxDegreeOfParallelism = maxConcurrentRunners > 0 ? maxConcurrentRunners : -1, CancellationToken = token }; var startOrderInt = 0; Parallel.ForEach(buildSortedAllActions, options, action => { //stdOut.Write(string.Format("\r> Starting: {0} \n", action.Name)); token.ThrowIfCancellationRequested(); runningTests.IncrementIndex(action.Index); var startOrder = Interlocked.Increment(ref startOrderInt); var startTime = totalRuntime.Elapsed; var sw = new Stopwatch(); sw.Start(); var exitCode = action.RunTests(); sw.Stop(); testResults.Add(new RunStats { Name = action.Name, StartTime = startTime, RunTime = sw.Elapsed, EndTime = totalRuntime.Elapsed, StartOrder = startOrder, FinishOrder = testResults.Count, ExitCode = exitCode }); runningTests.IncrementIndex(action.Index); if (exitCode != 0) { //Go to TestFailure runningTests.IncrementIndex(action.Index); if (!Console.IsOutputRedirected) stdOut.Write("\r! Test failure: {0} ({1}) \n", action.Name, exitCode); } if (exitCode < 0) { //Go to RunFailure runningTests.IncrementIndex(action.Index); } }); }
private static void CreateThread(TestRunAction action, CancellationToken token, TextWriterWrapper stdOut, ProgressStats runningTests, Stopwatch totalRuntime, ConcurrentBag<RunStats> testResults) { var startOrder = Interlocked.Increment(ref _startOrderInt); var parameters = new MethodParameters { Action = action, RunningTests = runningTests, StartOrderInt = startOrder, StdOut = stdOut, TestResults = testResults, Token = token, TotalRuntime = totalRuntime }; Interlocked.Increment(ref _threadCounter); //Shouldn't really use built-in thread pool for long-running processes... ThreadPool.QueueUserWorkItem(RunTest, parameters); }