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();

OnRecvStdOut現在、すべての IO( ) 操作が完了するまでプログラムに待機させる方法を探しています。

私はSystem.Threadingクラスのいずれかを使用することについて考えましたが、どのクラスがこれに最適で、結局これを行う方法がわかりません。おそらく最良の方法は次のとおりです。

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

そしてメイン関数では:

something.WaitUntilZero();

StdErr注: と の両方をStdOut並行して処理できるようにしたいと思います。 とのペアが発生する前に何度も呼び出されるため、が と同じくらい呼び出されるとは限りSomethingません。WaitSignalIncrease()DecreaseAndSignal()Wait

2番目に頭に浮かんだのは、(シグナルを処理する必要なしに)何度もシグナルを送信し、次のようなメイン関数でループを使用できるものでした。

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

2に設定して使用しCountdownEventます。各データ受信コールバックで、x.EndOfStreamフラグを確認します(xはプロセスオブジェクトのstandardoutputまたはstandarderrorです)。EOFの場合は、カウントダウンイベントを通知します。標準出力ストリームとエラー出力ストリームの両方が最終的にイベントを通知するため、これは機能します。両方がそれを合図すると、それを待つことが戻ります。それはまたそれをするための非常に効率的な方法です。

于 2012-12-18T02:50:11.720 に答える