当Process.WaitForExit与硬超时一起使用时,如何等待输出流

时间:2017-02-22 14:50:45

标签: c# .net

这是一种非常令人惊讶的结果的“犯罪研究” - 至少对我而言。

我们正在使用Process对象运行外部命令。我们正在异步地捕获标准输出(和标准错误 - 我已经从样本中删除了这个以清除原因)。这里已经多次回答了这个问题。代码看起来像这样,工作正常:

var process = new Process
{
    StartInfo =
    {
        UseShellExecute = false,
        RedirectStandardOutput = true,
        FileName = @"...\TestApp.exe"
    }
};
process.OutputDataReceived += Process_OutputDataReceived;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
process.OutputDataReceived -= Process_OutputDataReceived;

现在,如果我想向WaitForExit()添加硬超时怎么办?简单:WaitForExit(int milliseconds)的重载版本。所以像这样的电话应该这样做:

process.WaitForExit(60000);

现在,这会导致输出捕获在某些情况下不完整。

这不是秘密,至少不是微软的开发人员。经过几个小时的研究,我得出的结论是WaitForExit的实现一定有问题。所以我看了一下代码,我在微软的实现中发现了这个评论:

// If we have a hard timeout, we cannot wait for the streams

这是我的问题 - 我做了很多评估而没有成功:

如何在WaitForExit()上进行硬超时,同时确保控制台输出捕获已完成?

2 个答案:

答案 0 :(得分:1)

您是否尝试在派生类中使用OnExited事件? See this。这可能允许您使用超时等待而不是将其传递给WaitForExit。

答案 1 :(得分:0)

@Hans Passant你的评论指引我走向正确的方向。实际上,我真的不知道Sleep()有多长。但我可以为此添加一个简单的看门狗。由于当我必须开始等待丢失的捕获时,该过程已经完成,我可以假设OutputDataReceived事件被持续触发,直到流为空。所以我所做的就是添加一个Stopwatch并在每次OutputDataReceived事件方法的开头重新启动它。在主代码中,我用以下代码替换了对WaitForExit(60000)的调用:

if (process.WaitForExit(60000))
{
   while (outputWatch.ElapsedMilliseconds < 20) Thread.Sleep(20);
}

好的,此代码中还有一个Thread.Sleep()。但它绝对算上0.05%...... :)。