public Job(int id, Process process, JobCallbackInfo callback = null) { logger.Info("Spawning new job id {0}; will call {1}", id, process.StartInfo.FileName); jobId = id; this.process = process; // if a progress port was specified in callback info, prepare for streaming if (callback != null && callback.ProgressPort > 0) { var streamEp = new IPEndPoint(callback.Address, callback.ProgressPort); CreateProgressStream(streamEp); streamingCollection = new BlockingCollection <string>(); process.OutputDataReceived += (s, a) => streamingCollection.Add(a.Data); process.ErrorDataReceived += (s, a) => streamingCollection.Add(a.Data); streamingLoopTask = Task.Factory.StartNew(StreamingLoopHandler); } else { output = new HelperFunctions.ThreadSafeStringBuilder(); process.OutputDataReceived += (s, a) => output.AppendLine(a.Data); process.ErrorDataReceived += (s, a) => output.AppendLine(a.Data); } // always log output process.OutputDataReceived += (s, a) => logger.Debug($"Job {this.jobId} std output: {a.Data}"); process.ErrorDataReceived += (s, a) => logger.Debug($"Job {this.jobId} std error: {a.Data}"); // add a logging message when a job finishes and ensure that streaming task stops if needed process.EnableRaisingEvents = true; process.Exited += (o, e) => logger.Info($"Job {id} finished executing."); process.Exited += (o, e) => streamingCollection?.Add(null); if (callback != null) { logger.Info("Registering job {0:d} for callbacks", id); // if callbacks are specified, we need to register for process events, and setup a handler callbackInfo = callback; // fire the callback handler in another thread (otherwise the callback might take a while and block other events waiting on exit) process.Exited += (o, e) => Task.Factory.StartNew(FireCompletionCallback); } process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); }
public static Job CreateJob(Process p, JobCallbackInfo callback = null) { var newid = Interlocked.Increment(ref nextJobId); return(new Job(newid, p, callback)); }