問候計算器件,輸出解析更新單個控制檯線路
在WPF前端的一個BackgroundWorker我運行在一個System.Diagnostics.Process
sox(開源控制檯聲音處理工具)。以同樣的方式,我使用其他幾個命令行工具並解析它們的輸出以在我的前端填充進度條。
這適用於其他工具,但不適用於Sox,因爲它不是爲每個進度步驟發送新行,而是通過僅使用回車符(\ r)和沒有換行符(\ n)更新控制檯上的一行)。我在process.StandardError
上嘗試了異步和同步讀取。
結合使用異步process.ErrorDataReceived += (sender, args) => FadeAudioOutputHandler(clip, args);
與process.BeginErrorReadLine();
不會產生任何的個人狀態更新,因爲某些原因,回車不觸發的ReadLine,即使MSDN docs認爲它應該。當過程完成時,輸出會在一個塊中吐出。
我然後通過炭嘗試了同步炭以下代碼讀取的流:
char[] c;
var line = new StringBuilder();
while (process.StandardError.Peek() > -1)
{
c = new char[1];
process.StandardError.Read(c, 0, c.Length);
if (c[0] == '\r')
{
var percentage = 0;
var regex = new Regex(@"%\s([^\s]+)");
var match = regex.Match(line.ToString());
if (match.Success)
{
myProgressObject.ProgressType = ProgressType.FadingAudio
//... some calculations omitted for brevity
percentage = (int) Math.Round(result);
}
else
{
myProgressObject.ProgressType = ProgressType.UndefinedStep;
}
_backGroundWorker.ReportProgress(percentage, myProgressObject);
line.Clear();
}
else
{
line.Append(c[0]);
}
}
上面的代碼似乎不讀取實時數據流,但將停止輸出一會兒。然後它會傳播一個小塊,最終在整個過程中發生死鎖。
任何提示朝着正確的方向將不勝感激!
更新與(不拘小節?)解決方案:
這讓我抓狂,因爲沒有什麼我想對事物的C#方似乎對結果產生任何影響。我最初的實現,在改變它15次並引入新的依賴之前,沒有問題。
問題在於單獨使用sox和RedirectStandardError。我發現在獲取sox源代碼並構建自己的版本之後。首先我完全刪除了sox的所有輸出,除了我真正感興趣的東西,然後將輸出更改爲全行,然後換行符\n
。我認爲這會解決我的問題。那麼,它沒有。我不知道足夠的C++來找出原因,但他們似乎已經緩和了stdio如何寫入該流,如何緩衝或以如此特殊的方式執行,以至於c#端的streamreader不會刷新到默認值4096字節緩衝區已滿。我確認通過填充每行至少4096字節。所以在最後我所要做的就是手動沖水標準錯誤中sox.c每個fprintf(stderr, ...)
通話後display_status(...)
:
fflush(stderr);
雖然,我不知道這是任何接近一個完美的解決方案。
感謝Erik Dietrich的回答,這讓我從不同的角度來看待這個問題。
關於sox的信息讓我感到好奇,所以我做了一些調查。這可能是一個遠射,但http://en.wikipedia.org/wiki/Setvbuf有有趣的可能性。它看起來像你可以通過文件句柄強制緩衝設置,而不是通過進程。這可以讓你'重寫'sox的默認行爲,這樣你就可以獨立保存它的源代碼,而不會在每次更新它們的東西時註定要手動更新。可能有一個託管的C#等價物,或者你可以只寫一個調用一個微小的C實用程序。 –