我正在运行一个运行driverquery.exe命令并返回输出
的程序 pProcess.StartInfo.CreateNoWindow = true;
debugLog.WriteToLog("");
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
debugLog.WriteToLog("before start method");
pProcess.Start();
debugLog.WriteToLog("after start method");
if (windowTitleToHide.Length > 0)
{
WindowsUtil.HideWindow(windowTitleToHide);
}
if (null != attributeName && !"".Equals(attributeName))
Console.WriteLine(attributeName + " : ");
debugLog.WriteToLog("before read to end");
StreamReader reader = pProcess.StandardOutput;
String strOutput = string.Empty;
while (reader.Peek() > -1)
strOutput += reader.ReadLine();
debugLog.WriteToLog("after read to end");
Console.WriteLine(strOutput);
debugLog.WriteToLog("before wait for exit");
pProcess.WaitForExit();
debugLog.WriteToLog("after wait for exit");
pProcess.Close();
这个过程大约需要30分钟才能完成。如果我通过cmd运行相同的过程,它总是在2分钟内完成。我尝试过使用readtoend而不是readline,但这也没有帮助。有人能告诉我这里有什么问题吗?在我的日志中,我可以看到最后一行在等待退出之前打印为
PS:当我看到taskmanager中的进程时,driverquery.exe正在运行但没有消耗任何CPU周期。调用此代码的过程消耗大约99%的CPU。我确信调用代码在运行此代码时没有执行任何其他任务。
答案 0 :(得分:2)
我猜可能与问题有关:
while (reader.Peek() > -1)
strOutput += reader.ReadLine();
您可能没有阅读应用程序的完整输出。如果其输出中有任何暂停,则reader.Peek()
将在应用程序完成其完整输出之前返回-1。如果输出大量数据,您甚至可能会溢出输出流,因为在清空流一次后,您的进程将放弃读取。如果是这种情况,子进程可能会生成大量异常输出到完整流(这将大大增加执行时间)。分析和调试会告诉您更多关于实际情况的信息。
您可以尝试这样的异步方法:
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.EnableRaisingEvents = true; // Enable events
pProcess.OutputDataReceived += outputRedirection; // hook up
pProcess.Start();
pProcess.BeginOutputReadLine(); // use async BeginOutputReadLine
pProcess.WaitForExit();
其中
static void outputRedirection(object sendingProcess,
DataReceivedEventArgs outLine)
{
try
{
if (outLine.Data != null)
Console.WriteLine(outLine.Data);
// or collect the data, etc
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
}
而不是在紧密循环中轮询(可能比子进程填充它更快地清空输出流,因此失败),而不是等待数据进入。你的主进程仍将阻塞调用到WaitForExit
但线程池线程将处理传入的事件。
编辑
这是SSCCE,效果很好:
static void Main(string[] args)
{
Stopwatch spw = new Stopwatch();
spw.Start();
Process pProcess = new Process();
pProcess.StartInfo.FileName = "driverquery.exe";
pProcess.StartInfo.CreateNoWindow = true;
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.EnableRaisingEvents = true;
pProcess.OutputDataReceived += outputRedirection;
pProcess.Start();
pProcess.BeginOutputReadLine();
pProcess.WaitForExit();
pProcess.Close();
spw.Stop();
Console.WriteLine();
Console.WriteLine("Completed in : " +
spw.ElapsedMilliseconds.ToString()
+ "ms");
}
使用上面定义的outputRedirection
- >输出:
如果这不适合您,请向我们展示您完整,真实的代码。你正在做的其他事情是错误的。