static async Task <ProcessStats> RunOneProcess(string commandline, string prefix, TextWriter outWriter, TextWriter errWriter, CancellationToken cancel, bool skipEmptyLines, bool writeStderr, ICollection <uint> procIDs) { log.dbg("starting: [{0}]", commandline); uint?currProcID = null; ProcessStats procStats = await ProcessRedirectAsync.Run( commandline, onProcessCreated : (uint procId) => { currProcID = procId; lock (procIDs) { procIDs.Add(procId); } }, onProcessOutput : (kind, line) => { if (kind == KINDOFOUTPUT.STDERR && !writeStderr) { return; } if (skipEmptyLines && String.IsNullOrWhiteSpace(line)) { return; } TextWriter writer = kind == KINDOFOUTPUT.STDOUT ? outWriter : errWriter; if (String.IsNullOrEmpty(prefix)) { writer.WriteLine(line); } else { writer.WriteLine(prefix + "\t" + line); } }); if (currProcID.HasValue) { lock (procIDs) { procIDs.Remove(currProcID.Value); } log.dbg("process ended: ID: {0}, ExitCode: {1}", currProcID.Value, procStats.ExitCode); } else { log.err("proc has no ID set. komisch...?"); } return(procStats); }
public static Stats Run(IEnumerable <ProcCtx> ProcessesToStart, TextWriter outStream, TextWriter errStream, int maxParallel, bool skipEmptyLines, bool quiet, bool writeStderr, Func <long> numberJobs) { ProcessRedirectAsync.Init(); Stats stats = new Stats(); if (numberJobs != null) { Task.Run(() => stats.AllItems = numberJobs()); } ICollection <uint> runningProcIDs = new HashSet <uint>(); using (CancellationTokenSource cts = new CancellationTokenSource()) using (TextWriter exitcodeWriter = TextWriter.Synchronized(new StreamWriter(@".\forp.ExitCode.txt", append: false, encoding: Encoding.UTF8))) { log.dbg($"starting with maxParallel: {maxParallel}"); var cancel = cts.Token; if (!quiet) { Console.Error.WriteLine("press 'q' to quit. 'h' for more keys."); } Task.Run(() => HandleKeys(cts, outStream, errStream, runningProcIDs)); var procs = new MaxTasks(); var procsTask = procs.Start( tasks: ProcessesToStart.Select( async(procToRun) => { ProcessStats procStats = await RunOneProcess(procToRun.commandline, procToRun.prefix, outStream, errStream, cancel, skipEmptyLines, writeStderr, runningProcIDs).ConfigureAwait(false); exitcodeWriter.WriteLine($"{procStats.ExitCode}\t{procToRun.commandline}"); Interlocked.Add(ref stats.procTotalTime, procStats.TotalTime.Ticks); Interlocked.Add(ref stats.procKernelTime, procStats.KernelTime.Ticks); Interlocked.Add(ref stats.procUserTime, procStats.UserTime.Ticks); }), MaxParallel: maxParallel, cancel: cts.Token); if (!quiet) { var status = new StatusLineWriter(); var currProcess = Process.GetCurrentProcess(); Misc.DoUntilTaskFinished(procsTask, TimeSpan.FromSeconds(2), () => WriteStatusLine(status, procs, currProcess, stats)); Console.Error.WriteLine(); } else { procsTask.Wait(); } } return(stats); }
public void Init() { ProcessRedirectAsync.Init(); }