/// <summary> /// De-schedule the current execution environment to sleep for some period. /// </summary> /// <param name="duration">Time to sleep.</param> /// <returns>Synchronization handle to continue execution after the sleep period.</returns> public static Result Sleep(TimeSpan duration) { Result result = new Result(TimeSpan.MaxValue); TaskTimerFactory.Current.New(duration, _ => result.Return(), null, TaskEnv.New()); return(result); }
private static Yield ExecuteProcess_Helper(string application, string cmdline, Stream input, Stream output, Stream error, Result <int> result) { // start process var proc = new Process(); proc.StartInfo.FileName = application; proc.StartInfo.Arguments = cmdline; proc.StartInfo.UseShellExecute = false; proc.StartInfo.CreateNoWindow = true; proc.StartInfo.RedirectStandardInput = (input != null); proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.Start(); // inject input if (input != null) { input.CopyTo(proc.StandardInput.BaseStream, long.MaxValue, new Result <long>(TimeSpan.MaxValue)).WhenDone(_ => { // trying closing the original input stream try { input.Close(); } catch { } // try closing the process input pipe try { proc.StandardInput.Close(); } catch { } }); } // extract output stream Result <long> outputDone = proc.StandardOutput.BaseStream.CopyTo(output, long.MaxValue, new Result <long>(TimeSpan.MaxValue)); // extract error stream Result <long> errorDone = proc.StandardError.BaseStream.CopyTo(error, long.MaxValue, new Result <long>(TimeSpan.MaxValue)); TaskTimer timer = TaskTimerFactory.Current.New(result.Timeout, delegate(TaskTimer t) { try { // NOTE (steveb): we had to add the try..catch handler because mono throws an exception when killing a terminated process (why? who knows!) proc.Kill(); } catch { } }, null, TaskEnv.New()); // wait for output and error streams to be done yield return(new AResult[] { outputDone, errorDone }.Join()); int?exitCode = WaitForExit(proc, result.Timeout); timer.Cancel(); proc.Close(); if (exitCode.HasValue) { result.Return(exitCode.Value); } else { result.Throw(new InvalidOperationException("Unable to access process exit code")); } }