2010-12-15 10 views
6

コンソール出力をWindowsフォームのテキストボックスにリダイレクトするときに問題があります。問題はスレッドに関連しています。私は、コンソールプログラムの出力をスレッドセーフな方法でテキストボックスにリダイレクトするにはどうすればよいですか?

// Handle the date received by the console process 
void proc_DataReceived(object sender, DataReceivedEventArgs e) 
{ 
    if (e.Data != null) 
    { 
     if ((e.Data.EndsWith("DONE.")) || (e.Data.EndsWith("FAILED.")) || 
      (e.Data.StartsWith("RESET"))) 
     { 
      // This crashes the application, but is supposedly the correct method 
      this.AppendText(e.Data + Environment.NewLine); 

      // This works, but the debugger keeps warning me that the call 
      // is not thread safe 
      //out_txtbx.AppendText(e.Data + Environment.NewLine); 
     } 
    } 
} 

コンソールのテキストは、このように追加され、キャプチャし、この出力ハンドラでデータを処理し、その後、次のように

private void RunConsoleApp() 
{ 
    Process proc = new Process(); 
    proc.StartInfo.FileName = "app.exe"; 
    proc.StartInfo.Arguments = "-a -b -c"; 
    proc.StartInfo.UseShellExecute = false; 

    // set up output redirection 
    proc.StartInfo.RedirectStandardOutput = true; 
    proc.StartInfo.RedirectStandardError = true;  
    proc.EnableRaisingEvents = true; 
    proc.StartInfo.CreateNoWindow = true; 

    // Set the data received handlers 
    proc.ErrorDataReceived += proc_DataReceived; 
    proc.OutputDataReceived += proc_DataReceived; 

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

    if (proc.ExitCode == 0) 
    { 
     out_txtbx.AppendText("Success." + Environment.NewLine); 
    } 
    else 
    { 
     out_txtbx.AppendText("Failed." + Environment.NewLine); 
    } 
} 

をコンソールアプリケーションを実行しています

delegate void AppendTextDelegate(string text); 

// Thread-safe method of appending text to the console box 
private void AppendText(string text) 
{ 
    // Use a delegate if called from a different thread, 
    // else just append the text directly 
    if (this.out_txtbx.InvokeRequired) 
    { 
     // Application crashes when this line is executed 
     out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), new object[] { text }); 
    } 
    else 
    { 
     this.out_txtbx.AppendText(text); 
    } 
} 

out_txtbx.Invokeが呼び出されたときにアプリケーションがクラッシュするという点を除いて、私が見てきたすべてのドキュメントと例が正しい方法です。

何が壊れている可能性があり、これを行うための代替方法はありますか? (ハンスアンパッサンで指摘したように)


ソリューション

問題はアプリがラインの結果として、「致命的な抱擁」で立ち往生していることである、

proc.WaitForExit(); 

その行は削除する必要があり、その方法は次のようになります。

private void RunConsoleApp() 
{ 
    Process proc = new Process(); 
    proc.StartInfo.FileName = "app.exe"; 
    proc.StartInfo.Arguments = "-a -b -c"; 
    proc.StartInfo.UseShellExecute = false; 

    // set up output redirection 
    proc.StartInfo.RedirectStandardOutput = true; 
    proc.StartInfo.RedirectStandardError = true;  
    proc.EnableRaisingEvents = true; 
    proc.StartInfo.CreateNoWindow = true; 

    // Set the data received handlers 
    proc.ErrorDataReceived += proc_DataReceived; 
    proc.OutputDataReceived += proc_DataReceived; 

    // Configure the process exited event 
    proc.Exited += new EventHandler(ProcExited); 

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

    // This blocks the main thread and results in "deadly embrace" 
    // The Process.Exited event should be used to avoid this. 
    //proc.WaitForExit(); 
} 

とイベントハンドラが提供されなければならない、

/// <summary> 
/// Actions to take when console process completes 
/// </summary> 
private void ProcExited(object sender, System.EventArgs e) 
{ 
    Process proc = (Process)sender; 

    // Wait a short while to allow all console output to be processed and appended 
    // before appending the success/fail message. 
    Thread.Sleep(40); 

    if (proc.ExitCode == 0) 
    { 
     this.AppendText("Success." + Environment.NewLine); 
     ExitBootloader(); 
    } 
    else 
    { 
     this.AppendText("Failed." + Environment.NewLine); 
    } 

    proc.Close(); 
} 
+2

どのようなエラーが表示されますか? – SLaks

+0

そしてどの行に? – decyclone

+0

私はこれを誤りなくしました。私のコードサンプルにアクセスできる時間までに適切な回答がない場合、私は投稿します。私が家に帰ると、これは今晩の後半になることに注意してください。テキストボックスに書き込んだ後、Console.SetOutをTextWriterに向けたTextWriterオブジェクトを作成しました。 http://msdn.microsoft.com/en-us/library/system.console.setout%28v=VS.90%29.aspx – IAbstract

答えて

9
proc.WaitForExit(); 

を試してみてください。メインスレッドはブロックされ、プロセスが終了するのを待ちます。それは、それが本質的な任務を世話するのを止める。 UIを更新したままにするまた、Control.Invoke()要求がディスパッチされていることを確認します。 AppendText()メソッドが完了するのを停止します。終了するプロセスを停止します。あなたのUIスレッドがWaitForExit()呼び出しを過ぎてから停止するのを止める。 「致命的な抱擁」、別名デッドロック。

メインスレッドをブロックすることはできません。代わりにProcess.Exitedイベントを使用します。

+0

おかげでハンス、それは完璧な意味が(今あなたがそれを説明した)。 –

0

は、それがデッドロックと呼ばれる

out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), text); 
+1

これは動作しません –

関連する問題