我需要运行一些外部exe,并读取其输出和错误。
prc = new Process();
prc.StartInfo.UseShellExecute = false;
prc.StartInfo.FileName = fileName;
prc.StartInfo.Arguments = arguments;
prc.StartInfo.LoadUserProfile = true;
prc.StartInfo.RedirectStandardOutput = true;
prc.StartInfo.RedirectStandardError = true;
prc.OutputDataReceived += (sendingProcess, outLine) => outputText.AppendLine(outLine.Data);
prc.ErrorDataReceived += (sendingProcess, errorLine) => errorText.AppendLine(errorLine.Data);
prc.Start();
prc.BeginOutputReadLine();
prc.BeginErrorReadLine();
发生这种情况的线程可能随时中止,我无法对其进行任何更改,因此我无法使用prc.WaitForExit();
因为它无法中止,直到进程本身被杀死。这意味着每次线程中止时,所有执行都会挂起。
所以我在单独的方法中用这个替换了它:
while (!Thread.CurrentThread.ThreadState.HasFlag(ThreadState.AbortRequested) && !Thread.CurrentThread.ThreadState.HasFlag(ThreadState.Aborted))
{
if (!process.HasExited) continue;
return process.ExitCode;
}
唯一的问题是输出。奇怪的是,有时输出和错误最终都会缺少字符串,添加Thread.Sleep
可以解决这个问题,这意味着异步写入由于某种原因无法跟上。
这似乎是一个微不足道的问题,但我找不到可靠的解决方案。 Thread.Sleep
几乎不是一个好的做法,执行时间非常重要。可靠地获取所有错误和输出的最佳方法是什么?
输出的问题在于,在进程退出之前,用于将其传送到进程的匿名管道的写入端可能不会被刷新 - 它并不总是发生,但你不能依赖它没有发生。相反,为什么不在单独的线程中运行进程内容,包括WaitForExit()
(或者只是WaitForExit()
(?您的原始线程可以等待该工作线程以Thread.Abort
可能的方式完成(例如 Thread.Join()
(,您将拥有完整的输出。或者,如果您不担心ThreadAbortException
但需要能够取消WaitForExit()
呼叫,则可以使用 WaitHandle.WaitAny(prc.Handle,cancellationToken.WaitHandle)
。