2010-10-29 51 views
0

下面是C#代碼我使用的是推出一個子進程並監控其輸出:C#:讀取子進程標準輸出塊,直到另一個子進程結束?

using (process = new Process()) { 
    process.StartInfo.FileName = executable; 
    process.StartInfo.Arguments = args; 
    process.StartInfo.UseShellExecute = false; 
    process.StartInfo.RedirectStandardOutput = true; 
    process.StartInfo.RedirectStandardInput = true; 
    process.StartInfo.CreateNoWindow = true; 
    process.Start(); 

    using (StreamReader sr = process.StandardOutput) { 
     string line = null; 
     while ((line = sr.ReadLine()) != null) { 
      processOutput(line); 
     } 
    } 

    if (process.ExitCode == 0) { 
     jobStatus.State = ActionState.CompletedNormally; 
     jobStatus.Progress = 100; 
    } else { 
     jobStatus.State = ActionState.CompletedAbnormally; 
    } 
    OnStatusUpdated(jobStatus); 
} 

我推出多個子進程在不同的線程池線程(但不超過四個的時間,在一個四核核心機器)。這一切工作正常。

我遇到的問題是我的一個子進程將退出,但對sr.ReadLine()的相應調用將阻塞,直到另一個子進程退出。我不確定它會返回什麼,但是這不應該發生,除非我缺少某些東西。

沒有任何關於我的子過程會導致他們以任何方式「鏈接」 - 他們不相互溝通。當發生這種情況時,我甚至可以查看任務管理器/進程資源管理器,並看到我的子進程已經退出,但標準輸出上的ReadLine()調用仍然被阻止!

我已經能夠通過將輸出監控代碼旋轉到新線程並執行process.WaitForExit()來解決此問題,但這看起來很奇怪。任何人都知道這裏發生了什麼?

回答

0

我認爲這不是你的代碼,這是問題。由於許多原因,阻止呼叫可能會解除阻止,這不僅是因爲他們的任務已完成。我不得不承認,但是在Unix世界裏,當一個孩子結束時,一個信號被髮送到父進程,這使得他從任何阻塞調用中喚醒他。這可以解除對父母期望的任何輸入的閱讀。

如果Windows的工作方式相似,這並不會讓我感到驚訝。無論如何,請仔細閱讀阻止呼叫可能會解除阻止的原因。

+0

這是它應該工作的方式。任何阻止調用在他們的任務不再相關時都不會解鎖的設計對我來說似乎是瘋了。在我的情況下,孩子結束了,但父母並沒有從阻止的呼叫中醒來。它看起來像某處有一個錯誤。 – jnylen 2010-10-29 21:04:28

2

有關ProcessStartInfo.RedirectStandardOutput的MSDN文檔詳細討論了在執行您在此處執行的操作時可能出現的死鎖。提供的解決方案使用ReadToEnd,但我想象當您使用ReadLine時適用相同的建議和補救措施。

同步讀取操作介紹 從StandardOutput流 和子進程寫入到 流中讀取來電 之間的依賴關係。這些依賴關係可能導致死鎖條件爲 。當呼叫者 從 子進程的重定向流中讀取時,它取決於 孩子。調用者等待讀取 操作,直到孩子寫入 流或關閉流。當 子進程寫入足夠的數據 以填充其重定向的流時,取決於父級,它是 。進程等待下一次寫入 操作,直到父節點從 讀取完整流或關閉流。 當 調用者和子進程等待 彼此完成操作, 並且都不能繼續時,死鎖條件結果。您可以通過評估 子進程和調用者之間的依賴關係來避免死鎖。

最好的解決辦法似乎是異步I/O,而不是同步方法:

您可以使用異步讀取 操作來避免這些依賴 及其僵局潛力。 或者,您可以通過創建兩個 線程並在單獨的線程上讀取每個 流的輸出來避免 死鎖狀況。

有一個樣本here如果你走這條路線應該對你有用。

+0

糾正我,如果我錯了,但我不認爲這是發生在這裏的事情,因爲子進程*已經退出並且不再運行*。另外,我現在正在創建一個額外的線程並讀取該線程上的輸出,如您最後的引用所示。 – jnylen 2010-10-29 21:12:08

+0

@jnylen - 你可能是對的,但你描述的行爲確實聽起來像是一個僵局,通過進一步的流程退出可以減輕壓力。如果其他進程沒有退出,你的第一個進程永遠是對的?這是一個可能的僵局。在互聯網上有足夠的抱怨,我會遵循MSDN對這封信的說明。無論如何,異步I/O肯定會更優雅? – 2010-10-29 21:15:21

+0

這可能是一個僵局,但我所看到的就像是不同過程之間的「遠距離的鬼怪行動」。我想知道爲什麼。異步I/O大致相當於我現在正在做的事情,但它可能更加優雅。我會在星期一看看。 – jnylen 2010-10-29 21:19:59

相關問題