1

注:この質問は最初のバージョンから大幅に変更されているため、コメントや回答が奇妙に見える場合があります。おかしなところがあれば編集履歴を確認してください。

C# クラス ライブラリから子プロセスを起動しています。

Process.BeginOutputReadLine()出力/エラーを非同期で読み取るために使用しています。非常に長い行では機能しないと思っていましたが、スケーラブルではないことが問題のようです。私のコンピューターでは、128 kb の行は即座に処理され、512 kb の行は約 1 分かかるようで、1 mb は数分かかるようで、10 mb の行が処理されるのを約 2 時間待ちました。私がキャンセルしたとき、それはまだ働いていました。

StandardOutput および StandardError ストリームからの直接読み取りを修正するのは簡単に思えますが、これらのストリームからのデータはバッファリングされているようです。標準出力からバッファを埋めるのに十分なデータを取得してから、標準エラー出力からさらにデータを取得した場合、それらのいずれかに保留中のデータがあるかどうかを確認する方法が見つかりません。標準エラー出力から読み取ろうとすると、ハングします永遠に。なぜこれが起こっているのか、何が間違っているのか、これを行う正しい方法は何ですか?

私が達成しようとしていることを説明するためのいくつかのコードサンプル。

Program1:

    // Writes a lot of data to stdout and stderr
    static void Main(string[] args)
    {
        int numChars = 512 * 1024;
        StringBuilder sb = new StringBuilder(numChars);

        String s = "1234567890";

        for (int i = 0; i < numChars; i++)
            sb.Append(s[i % 10]);

        int len = sb.Length;
        Console.WriteLine(sb.ToString());
        Console.Error.WriteLine(sb.ToString());
    }

Program2:

    // Calls Program1 and tries to read its output.
    static void Main(string[] args)
    {
       StringBuilder sb = new StringBuilder();
       StringBuilder sbErr = new StringBuilder();

       proc.StartInfo.CreateNoWindow = true;
       proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
       proc.StartInfo.UseShellExecute = false;

       proc.StartInfo.RedirectStandardError = true;
       proc.StartInfo.RedirectStandardOutput = true;
       proc.StartInfo.RedirectStandardInput = false;

       proc.StartInfo.Arguments = "";
       proc.StartInfo.FileName = "program1.exe";

       proc.ErrorDataReceived += (s, ee) => { if (ee.Data != null) sbErr.AppendLine(ee.Data); };
       proc.OutputDataReceived += (s, ee) => { if (ee.Data != null) sb.AppendLine(ee.Data); };

       proc.Start();
       proc.BeginOutputReadLine();
       proc.BeginErrorReadLine();
       proc.WaitForExit();
    }

Program1生成するデータのサイズを設定できる定数があり、Program2起動Program1してデータの読み取りを試みます。時間がサイズに比例して増加すると予想する必要がありますが、それよりもはるかに悪いようです.

4

1 に答える 1

0

あなたの問題を理解していただければ幸いです。アプリケーションがハングアップするのは、プロセスが終了するのを待つためProcess.WaitForExit()です。Process.WaitForExit()

新しいスレッドで呼び出すことができます: int プロセスを作成するメソッド:

    Thread trd = new Thread(new ParameterizedThreadStart(Start));
     trd.Start();

このメソッドを追加します。

  private void Start(object o)
  {
     ((Process)o).WaitForExit();
     // your code after process ended
  }
于 2013-09-10T10:09:00.317 に答える