Streamreader.Read blocks / RedirectStandardOutput使用

时间:2012-05-31 18:23:31

标签: c# process

我正在尝试使用StreamReader从进程读取输出数据,但StreamReader阻塞并且不会返回任何输出。

我的流程看起来像这样:

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = args;
startInfo.FileName = filename;
StartInfo.WorkingDirectory = aDirectory;
StartInfo.UseShellExecute = false;
StartInfo.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = startInfo;
p.Start();

之后调用StreamReader:

StreamReader strmRead = p.StandardOutput;
char[] output = new char[4096];
while(true){
   strmRead.Read(output,0,output.Length);
   string outputString = new string(output);
   Debug.WriteLine(outputString);
}

代码在调用Read方法时挂起。当我手动终止程序时,进程的输出将写入调试控制台。进程输出不使用换行符,因此使用Process.OutputDataReceived不起作用。如何从流中获取流程输出而不会无限期地阻塞?

编辑:鉴于我已经得到的答案,似乎问题是流程没有放弃标准输出或不刷新输出而不是我的代码有什么问题。如果其他人有任何见解,请随时发表评论。

3 个答案:

答案 0 :(得分:1)

您正在读取4096个字节,可能会有更少,因此流阻塞。

此外,还有更有效的方法从流中读取文本。 TextReaderReadLine方法,请尝试相反。

http://msdn.microsoft.com/en-us/library/system.io.textreader.readline.aspx

BTW,while (true) ???你打算如何退出?

答案 1 :(得分:1)

你可以这样做:

String outputString = strmRead.ReadToEnd();

答案 2 :(得分:1)

我知道这个问题很老了。但我遇到了类似的问题。我尝试使用Peek()方法,但即使Peek()返回-1,它也不总是流的结尾。

我通过启动一个新线程来解决我的问题,当Peek()返回-1时,它尝试读取下一个字符。

                    string toRead = "";
                    do
                    {
                        if (reader.Peek() == -1)
                        {
                            Thread td = new Thread(TryReading);
                            td.Start();
                            Thread.Sleep(400);
                            if (ReadSuccess == false)
                            {
                                try
                                {
                                    td.Abort();
                                }
                                catch (Exception ex) { }
                                break;
                            }
                            else
                            {
                                toRead += ReadChar;
                                ReadSuccess = false;
                            } 
                        }
                        toRead += (char)reader.Read();
                    } while (true);

这里定义了TryReading()方法:

static char ReadChar = 'a';
static bool ReadSuccess = false;

static void TryReading(object callback)
{
    int read = reader.Read();
    ReadChar = (char)read;
    ReadSuccess = true;
}

基本上......如果线程花了太长时间来阅读这个角色 - 我中止它并使用它到目前为止所阅读的文字。

这解决了我的问题。