关于执行外部流程

时间:2018-01-15 08:56:55

标签: c# system.diagnostics

我需要运行一些外部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不是一个好习惯,执行时间非常重要。可靠地获取所有错误和输出的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

输出的问题是,用于将其传递到进程的匿名管道的写入结束可能不会被刷新,直到进程退出 - 它并不总是发生,但是你不能依赖它正在发生。相反,为什么不在一个单独的线程中运行进程内容,包括WaitForExit()(或者只是WaitForExit())?您的原始帖子可以等待此工作人员以Thread.Abort方式完成(例如Thread.Join()),您将获得完整的输出。或者,如果您不担心ThreadAbortException但需要能够取消WaitForExit()来电,则可以使用WaitHandle.WaitAny(prc.Handle,cancellationToken.WaitHandle)