我從C#應用程序啓動另一個進程,並出現問題:有什麼方法可以讀取進程輸出char-by-char,而不是逐行嗎?我非常需要這樣做,因爲另一個進程是一個命令行引擎,我需要向它發送一個命令,讀取輸出並以某種方式理解它何時完成。它表示的方式是在沒有換行的情況下編寫提示,所以我沒有機會捕捉到它。現在使用易碎定時器的東西,並尋找更好的解決方案。.NET IO重定向 - 通過字符讀取輸出字符
MSDN中概述的C#過程API和other places只允許逐行輸入 - 即使採用異步方式。
我從C#應用程序啓動另一個進程,並出現問題:有什麼方法可以讀取進程輸出char-by-char,而不是逐行嗎?我非常需要這樣做,因爲另一個進程是一個命令行引擎,我需要向它發送一個命令,讀取輸出並以某種方式理解它何時完成。它表示的方式是在沒有換行的情況下編寫提示,所以我沒有機會捕捉到它。現在使用易碎定時器的東西,並尋找更好的解決方案。.NET IO重定向 - 通過字符讀取輸出字符
MSDN中概述的C#過程API和other places只允許逐行輸入 - 即使採用異步方式。
我還沒有嘗試過,但下面的方法可能工作,以避免忙循環:
但是,爲防止繁忙的循環,這是一項非常多的工作。就個人而言,我會建議一個增量退避等待循環,以防止使用太多的系統資源。類似於(僞代碼):
int waittime = 1;
bool done = false;
while (true)
{
ReadAsMuchAsIsAvailable();
if (TheAvailableOutputEndsInAPrompt())
{
break;
}
Sleep (waittime);
waittime++; // increase wait time
waittime = min(waittime, 1000); // max 1 second
}
這將對快速命令產生快速的操作結束檢測,對於慢速命令則產生較慢的結果。這意味着您可以執行大量的快速命令並快速檢測它們的結束,而較長的命令可能會有1秒的開銷(考慮到命令本身的大小,這不會引人注意)。
這是一個啓動的過程的示例程序中,並通過線由字符讀取標準輸出,字符和不行:
static void Main(string[] args)
{
var process = new Process();
process.StartInfo = new ProcessStartInfo(@"C:\Windows\System32\cmd.exe", "/c dir");
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
var outReader = process.StandardOutput;
while (true)
{
if (!outReader.EndOfStream)
Console.Write((char)outReader.Read() + ".");
if (outReader.EndOfStream)
Thread.Sleep(1);
}
}
小聲明 - 這是在沒有時間敲起來,並且我沒有證明有關時間的問題(如果在我們抓住標準輸出之前流程退出 - 我知道這種情況不太可能發生)。但是,就你的特定問題而言,它表明一個人不需要逐行閱讀(畢竟你是在處理一個StreamReader
)。
更新:根據建議,包括一個Thread.Sleep(1)
產生線程。顯然有使用Thread.Sleep(0)
,儘管關於此事的MSDN文檔(較低優先級的線程沒有給出時間)的問題。並且是的,這是一個無限循環,並且必須有一些線程管理的東西來完成這個過程。
這需要一個單獨的線程來始終檢查EndOfStream屬性,這是高CPU佔用率的一種方式。我正在尋找一種方式讓流在新的字節到達時通知我 - 任何想法? – 2009-08-14 09:37:13
我可能會做類似的事情。也許加入一個小小的睡眠,並將其放入NewChar事件或類似的課程中。 – Svish 2009-08-14 10:10:39
是否有任何理由不能只使用StreamReader的BaseStream屬性,並使用BeginRead和EndRead方法在異步莊園中執行此操作? – 2013-11-08 01:31:06
char[] x = {' '};
System.IO.StreamReader reader = new StreamReader("c:\\file.txt");
while (!reader.EndOfStream)
{
reader.ReadBlock(x, 0, 1);
// x contains the current char in the reader.
}
這應該有效。
編輯:
那麼如何有關使用此:
x = reader.ReadToEnd().ToCharArray();
與以前相同的評論 - 我需要始終調用EndOfStream來檢查是否有新數據到達。在這裏尋找更聰明的方法.. – 2009-08-14 09:44:20
ReadToEnd()將阻止執行,直到流被關閉......這不是我所需要的。 – 2009-08-14 16:02:14
謝謝,這是我最終完成的(增量退避等待循環)。推出這個循環作爲一個單獨的線程,它現在很好地工作。 – 2009-08-17 20:06:15