2013-03-26 91 views
2

我有一个程序(服务器),它将四行输出打印到控制台,然后开始监听来自客户端程序的传入连接。从另一个程序读取标准输出

我有另一个程序(测试仪),我想从服务器读取标准输出并分析它。我已经安装了测试程序来启动服务器,并得到其输出如下:

Process server = new Process(); 
server.StartInfo.FileName = "server.exe"; 
server.StartInfo.UseShellExecute = false; 
server.StartInfo.RedirectStandardInput = true; 
server.StartInfo.RedirectStandardOutput = true; 
server.StartInfo.RedirectStandardError = true; 
server.Start(); 
StreamReader serverOutput = server.StandardOutput; 
string line = serverOutput.ReadToEnd(); 
... 

我遇到的问题是,当我执行服务器自己(或当我与测试执行它不重定向输出)我可以在控制台上看到所有四行。但是,当我使用上面的代码将服务器输出重定向到测试程序时,测试程序挂在“ReadToEnd”命令上,就好像它正在等待来自服务器的更多输出一样。

我也尝试使用“ReadLine”命令并将其放入一个FOR循环中重复4次。当我这样做时,前三行输出成功,然后挂在第4行“ReadLine”上,并且从不检索第4行的服务器输出。

最后,我也尝试使用“读取”命令尝试逐个获取字符,并且仍然无法从服务器输出的第4行获取任何字符。

任何有关我在这里失踪的建议?

更新: 经过大量的搜索后,我终于确定问题与输出缓冲有关。服务器程序(用C++编写)写入cout,这似乎在打印到屏幕时自动刷新,但在将stdout重定向到测试程序时不会自动刷新。我可以将setvbuf(stdout, NULL, _IONBF, 0);添加到服务器程序中,以使标准输出不被缓冲,但我更愿意找到另一种不涉及更改服务器程序的解决方案。

+0

可能重复的[StandardOutput.ReadToEnd()挂起](http://stackoverflow.com/questions/7160187/standardoutput-readtoend-hangs) – 2013-03-26 17:55:10

回答

1

流结束时将返回ReadToEnd。当程序关闭时会发生这种情况。

您可以尝试使用事件处理程序server.OutputDataReceived读取数据。这样你就可以异步接收它,而不会阻塞你的程序。

+0

事实上,我尝试了异步第一(使用'server.OutputDataReceived' ),但它也不起作用。同样的问题 - 它只挑选了前三行,并没有显示任何后续行。那时我开始尝试同步。顺便提一句,我确实想阻止我的程序(即服务器输出一些值,然后测试者验证写入的内容,然后发送数据以使服务器继续运行)。只是,无论我尝试过什么,我都无法让测试者拿起三条以上的线。 – user2212659 2013-03-26 20:34:54

0

昨天我在试图解决这个问题时发现了这个问题,所以我想我会用我找到的解决方案来回答它,只是为了后人。

我遇到的问题是process.WaitForExit调用在完成读取之前关闭输出流。通过在调用WaitForExit之前在Tasks和Wait中运行ReadLine循环,我设法获得所有输出(在本例中为Git调用)。

希望这有助于某人。的

var psi = new ProcessStartInfo(@"C:\Program Files (x86)\Git\bin\git.exe", "push " + remoteUrl + " " + branch) 
{ 
    UseShellExecute = false, 
    RedirectStandardOutput = true, 
    RedirectStandardError = true 
}; 

var process = new Process 
{ 
    StartInfo = psi 
}; 

Console.WriteLine("Pushing..."); 

process.Start(); 

var stdOutTask = Task.Factory.StartNew(() => 
{ 
    string str; 
    while ((str = process.StandardOutput.ReadLine()) != null) 
    { 
     Console.WriteLine(str); 
    } 
}); 
var stdErrorTask = Task.Factory.StartNew(() => 
{ 
    string str; 
    while ((str = process.StandardError.ReadLine()) != null) 
    { 
     Console.WriteLine(str); 
    } 
}); 

stdOutTask.Wait(); 
stdErrorTask.Wait(); 
process.WaitForExit(); 
process.Close(); 
相关问题