【问题标题】:Streamreader.Read blocks / RedirectStandardOutput used使用 Streamreader.Read 块/RedirectStandardOutput
【发布时间】:2012-05-31 18:23:30
【问题描述】:

我正在尝试使用 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 不起作用。如何在不无限期阻塞的情况下从流中获取进程输出?

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

【问题讨论】:

  • 我编辑了你的问题的标题,以便更好地提出你的问题,也许你会得到一些更有用的答案。

标签: c# process


【解决方案1】:

您正在读取 4096 字节,可能会更少,因此流块。

此外,还有更有效的方法可以从流中读取文本。 TextReaderReadLine 方法,试试吧。

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

顺便说一句,while (true) ???你打算如何退出?

【讨论】:

  • +1 StreamReader 也有 ReadLine 和 ReadToEnd 这可能很有用。
  • 输出中没有换行符,所以 ReadLine 也会阻塞。
  • 如果我将字节数更改为 4 而不是 4096,程序仍然会阻塞。
  • 嗯,您是否尝试了其他一些过程,也许刷新输出的方式有所不同?
  • 好的,代码可以在不同的进程中正常工作。输出刷新如何影响它?当我不重定向输出时,我可以看到它立即出现在控制台窗口中。
【解决方案2】:

你可以这样做:

String outputString = strmRead.ReadToEnd();

【讨论】:

  • 使用 ReadToEnd 而不是 Read 会发生完全相同的情况。
  • this。它在几段后讨论了死锁条件。
  • 所以你是说这个过程永远不会放弃让 StreamReader 从中读取的标准?
  • 我真的不确定。在您的代码和 msdn 的 sn-p 之间来回查看,您似乎在做基本相同的事情。
【解决方案3】:

我知道这个问题已经很老了。但我有一个类似的问题。我尝试使用 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;
}

基本上...如果线程读取字符的时间过长 - 我中止它并使用它到目前为止读取的文本。

这解决了我的问题。

【讨论】:

    猜你喜欢
    • 2016-02-02
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 2017-03-06
    • 2011-09-14
    • 1970-01-01
    相关资源
    最近更新 更多