2009-11-15 58 views
3

在我的應用程序中的主窗體啓動一個新的線程,然後打開另一個窗體,作爲一個進度窗口。 線程在2個控制檯應用程序之間管理一些數據,將來自StandardError的信息發送到進度窗口。我使用DataReceivedEventHandler異步讀取standarderror。C#與重定向標準錯誤的問題

如果我讓所有事情都能順利進行,那麼它就可以很好地工作,但是當用戶按下我的表單上的「取消」按鈕時會出現問題。會發生什麼,即使在我停止進程之後,ErrorDataReceived函數也會繼續啓動!有時取消會成功,但有時我會遇到死鎖狀況(我認爲這是正確的詞)。

這是我的代碼的一些片段,所以你可以看到發生了什麼。它卡在等待「p2.WaitForExit();」和「Invoke(new updateProgressDelegate(this.updateProgress),e.Data);」 (視覺工作室把一個綠色箭頭那些線,並說他們將執行下一個)

// start 2 processes (p & p2) and pipe data from one to the other 
// this runs in thread t 
        p.Start(); 
        p2.Start(); 
        byte[] buf = new byte[BUFSIZE]; 
        int read = 0; 
        p2.ErrorDataReceived += new DataReceivedEventHandler(p2_ErrorDataReceived); 
        p2.BeginErrorReadLine(); 

        try 
        { 
         read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE); 
         while (read > 0 && read <= BUFSIZE) 
         { 
          if (canceled==false) 
           p2.StandardInput.BaseStream.Write(buf, 0, read); 
          if (canceled==false) 
           read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE); 
          else 
          { 
           return; 
          } 
         } 
        } 


// this function is called when a user presses the "cancel" button on a form. 
private void cancel_encode() 
     { 

      if (p2 != null) 
      { 
       if (p2.HasExited == false) 
        p2.Kill(); 
       if (p2.HasExited == false) 
        p2.WaitForExit(); 
      } 
      if (p != null) 
      { 
       if (p.HasExited == false) 
        p.Kill(); 
       if (p.HasExited == false) 
        p.WaitForExit(); 
      } 
      if (t.IsAlive) 
      { 
       if (!t.Join(2000)) 
        t.Abort(); 
      } 
     } 


// this function sends the error data to my progress window 
void p2_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
     { 
      if (e.Data != null && canceled == false) 
       Invoke(new updateProgressDelegate(this.updateProgress), e.Data); 
     } 

回答

1

兩件事情

在「p2_ErrorDataReceived」,你可以調用的invoke()。這可能會導致部分死鎖。您可能想要將其更改爲BeginInvoke()。

Process.WaitForExit()的文檔建議您在調用Kill()之後,應該調用WaitForExit重載,它接受一個整數,如果返回true,則不帶參數再次調用它以確保所有異步處理已完成:

p2.Kill(); 
if(p2.WaitForExit(waitTime)) //waitTime is the number of milliseconds to wait 
{p2.WaitForExit();} //waits indefinitely 

//likewise for p 

http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx

+0

使用的BeginInvoke()似乎已經解決了!謝謝。 – Zarxrax 2009-11-16 00:34:31