處理大型數據流標準輸出重定向時WaitForExit掛起的問題
通過ProcessStartInfo
執行進程時,可能會遇到與StandardOutput
緩衝區限制相關的問題。具體來說,當重定向StandardOutput
時,如果輸出大小超過某個閾值(例如7MB),程序可能會在WaitForExit
期間無限期掛起。
原因
當重定向StandardOutput
且內部緩衝區已滿時,就會發生此行為。如果調用進程在讀取StandardOutput
之前等待目標進程退出,則目標進程在嘗試寫入已滿的緩衝區時會被阻塞,從而阻止其結束。相反,如果調用進程使用ReadToEnd
檢索輸出,則如果目標進程不關閉StandardOutput
(例如,如果它不終止或其StandardError
流被阻塞),它可能會被阻塞。
解決方案
為了解決這個問題,請使用異步讀取以防止緩衝區達到容量。以下代碼示例演示瞭如何執行此操作:
<code class="language-csharp">using (Process process = new Process()) { process.StartInfo.FileName = filename; process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; StringBuilder output = new StringBuilder(); StringBuilder error = new StringBuilder(); using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false)) using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false)) { process.OutputDataReceived += (sender, e) => { if (e.Data == null) { outputWaitHandle.Set(); } else { output.AppendLine(e.Data); } }; process.ErrorDataReceived += (sender, e) => { if (e.Data == null) { errorWaitHandle.Set(); } else { error.AppendLine(e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); if (process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout)) { // 进程已完成。在此处检查 process.ExitCode。 } else { // 超时。 } } }</code>
此解決方案使用異步回調來處理從StandardOutput
和StandardError
接收到的數據,確保內部緩衝區不會滿並防止死鎖。
注意:為了避免在發生超時時出現ObjectDisposedException
,請在訪問進程的輸出或錯誤流之前檢查進程的HasExited
屬性。
以上是為什麼WaitForexit失速使用大型數據流將標準輸出重定向時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!