参见下面的类,我用它来读取添加到它的任何进程的输出。目前我正在启动一个 Jar,它充当 C# 应用程序和 JMS 消息传递代理之间的 channel 适配器。唯一的问题是,当从进程的 StandardOutput
读取时,线程会阻塞 reader.Peek()
调用。
经过一些调试后,我发现只有当没有输出写入进程的 StandardOutput
流时才会发生这种情况。我已经对即时窗口进行了一些尝试,以确定是否可以找到一种方法来确定基础流是否为空。但到目前为止,对 Stream.CanRead
或 FileStream.Length
等属性的所有调用都会抛出 InvalidOperationExceptions
或返回无法用于检查此条件的输出.
此外,我还尝试使用 OutputDataReceived
和 ErrorDataReceived
事件,但出于某种原因,它们似乎从未触发。
所以我的问题是;有没有什么方法可以用来在进程输出可用时清晰地读取它?
读取输出的类:
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
实现中的一个已知错误,如 this answer 中所建议的那样.您的解决方法是使用异步流方法,例如 StreamReader.ReadAsync
或 StreamReader.ReadLineAsync
.
关于c# - 从进程中读取,StreamReader.Peek() 未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24252408/