6

我有启动子进程stdout异步处理它的应用程序。问题是异步操作需要一些时间,我希望负责流程执行的方法在所有异步 IO 操作完成后结束。

我有这样的代码:

using System.Diagnostics;

Process process = new Process();
// ...
process.OutputDataReceived += new DataReceivedEventHandler(this.OnRecvStdOut);
process.ErrorDataReceived += new DataReceivedEventHandler(this.OnRecvStdErr);
// ...
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
// ...
process.WaitForExit();

现在我正在寻找一种方法来告诉程序等到所有 IO ( OnRecvStdOut) 操作完成。

我虽然关于使用System.Threading类之一,但我不确定哪个类最适合这个以及如何做到这一点,最好的方法可能是:

public void OnRecvStdOut(...)
{
    something.Increase();
    // the stuff that takes so long
    something.DecreaseAndSignal();
}

在主要功能中:

something.WaitUntilZero();

注意:我想同时允许StdErrStdOut并行处理。 Something不能依赖它Wait会被调用Signal,因为Increase()DecreaseAndSignal()对在发生之前会被调用很多次Wait

想到的第二件事是能够多次发出信号(无需处理信号)并在主函数中使用循环,例如:

while( ioOperations > 0){
    something.WaitForSignal(500);
}

编辑:当前工作解决方案:

我想出了这个似乎有效的方法:

using System.Threading;

protected int IOCount = 0;
protected AutoResetEvent _IOSyncEvent = new AutoResetEvent(false);

public void OnRecvStdOut(...)
{
    Interlocked.Increase( ref IOCount);
    // the stuff that takes so long
    Interlocked.Decrease( ref IOCount);
    IOSyncEvent.Set();
}

// After process.WaitForExit()
while( IOCount > 0){
    // 250 for a case that signal occurs after condition and before wait
    IOSyncEvent.WaitOne(250); 
}

但我会很感激任何笔记如何做到这种“良好的实践方式”或者我认为实施的可能风险是什么。

4

1 回答 1

1

使用CountdownEvent设置为 2。每个接收到的数据回调,检查 x.EndOfStream 标志(其中 x 是过程对象上的标准输出或标准错误)。如果 EOF,则发出倒计时事件信号。它会起作用,因为标准和错误输出流最终都会发出事件信号。一旦两者都发出信号,它的等待将返回。这也是一种非常有效的方法。

于 2012-12-18T02:50:11.720 回答