从进程中读取,StreamReader.Peek()没有按预期工作



请参阅下面的类,我使用它读取添加到其中的任何进程的输出。目前,我正在启动一个Jar,它充当c#应用程序和JMS消息传递代理之间的通道适配器。唯一的问题是,当从进程的StandardOutput读取时,线程阻塞了reader.Peek()调用。

经过一些调试,我发现只有在没有输出写入进程的StandardOutput流时才会发生这种情况。我已经玩弄了一下即时窗口,以弄清楚我是否能找到一种方法来确定底层流是否为空。但是到目前为止,所有对Stream.CanReadFileStream.Length等属性的调用都会抛出InvalidOperationExceptions或返回不能用于检查此条件的输出。

此外,我还尝试使用OutputDataReceivedErrorDataReceived事件,但由于某种原因,它们似乎从未触发。

我的问题是;有没有什么方法可以在输出可用时干净地从流程读取输出?

读取输出的类:

namespace ReparatieSysteem.Lib
{
    internal delegate void NewOutputLineEvent(Process process, int port, string line);
    class ProcessListener
    {
        private static readonly Dictionary<int, Process> processes;
        private static readonly Thread thread;
        static ProcessListener()
        {
            processes = new Dictionary<int, Process>();
            thread = new Thread(RunThread);
            thread.Start();
        }
        private static void PollProcesses()
        {
            foreach (var item in processes.Where(p => p.Value.HasExited).ToList())
            {
                processes.Remove(item.Key);
            }
            foreach (var item in processes)
            {
                SendLines(item.Value, item.Key, ReadReader(item.Value.StandardError));
                SendLines(item.Value, item.Key, ReadReader(item.Value.StandardOutput));
            }
        }
        private static void SendLines(Process process, int port, IEnumerable<String> lines)
        {
            foreach(var line in lines)
            {
                if (OnNewOutput != null)
                {
                    OnNewOutput(process, port, line);
                }
            }
        }
        private static IEnumerable<string> ReadReader(StreamReader reader)
        {
            while (reader.Peek() >= 0)
            {
                yield return reader.ReadLine();
            }
        }
        private static void RunThread()
        {
            while(true)
            {
                if (processes.Count > 0)
                {
                    PollProcesses();
                }
                Thread.Sleep(200);
            }
        }
        public static void AddProcess(int port, Process process)
        {
            processes.Add(port, process);
        }
        public static event NewOutputLineEvent OnNewOutput;
    }
}

创建进程的代码:

var procStartInfo = new ProcessStartInfo("java", 
            string.Format("-jar {0} {1} {2} {3}", JarPath, ConnectionName, _listenQueue, _listenPort))
        {
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        _brokerProcess = new Process { StartInfo = procStartInfo };
        _brokerProcess.Start();
        ShutdownListener.OnApplicationQuit += _brokerProcess.Kill;
        ProcessListener.AddProcess(_listenPort, _brokerProcess);

似乎这是StreamReader实现中的一个已知错误,正如这个答案所建议的那样。在这种情况下,解决方法是使用异步流方法,如StreamReader.ReadAsyncStreamReader.ReadLineAsync

相关内容

  • 没有找到相关文章