我目前正在将命令行流程的输出呈现到文本框中。问题是在正常的命令提示符窗口中,写入的一行有一个加载栏类的东西......每隔几秒就输出一个“。”到屏幕....几点后,它将开始一个新的行,然后继续加载,直到它完成它的过程。
使用以下代码,而不是获取这些“。”一个接一个地出现,我的OutputDataRecieved正在等待写出整行...所以加载条没用......就是它等待“.............”和然后它就会对它起作用。
有没有办法跟踪输出到屏幕的每个字符,而不是每行输出似乎是什么?
//Create process
System.Diagnostics.Process process = new System.Diagnostics.Process();
// arguments.ProcessStartInfo contains the following declaration:
// ProcessStartInfo = new ProcessStartInfo( "Cmd.exe" )
// {
// WorkingDirectory = executableDirectoryName,
// UseShellExecute = false,
// RedirectStandardInput = true,
// RedirectStandardOutput = true,
// CreateNoWindow = true,
// }
process.StartInfo = arguments.ProcessStartInfo;
//Start the process
StringBuilder sb = new StringBuilder();
bool alreadyThrownExit = false;
// The following event only seems to be run per line output rather than each character rendering the command line process useless
process.OutputDataReceived += ( sender, e ) =>
{
sb.AppendLine( e.Data );
CommandLineHelper.commandLineOutput = sb.ToString();
arguments.DelegateUpdateTextMethod();
if( !alreadyThrownExit )
{
if( process.HasExited )
{
alreadyThrownExit = true;
arguments.DelegateFinishMethod();
process.Close();
}
}
};
process.Start();
process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );
process.BeginOutputReadLine();
答案 0 :(得分:1)
如果希望基于每个字符异步处理给定进程的stdout,则可以使用TextReader.ReadAsync()
方法。而不是你必须处理OutputDataReceived
事件的代码,只需执行以下操作:
process.Start();
// Ignore Task object, but make the compiler happy
var _ = ConsumeReader(process.StandardOutput);
process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );
其中:
async Task ConsumeReader(TextReader reader)
{
char[] buffer = new char[1];
while ((await read.ReadAsync(buffer, 0, 1)) > 0)
{
// process character...for example:
Console.Write(buffer[0]);
}
}
或者,您可以创建一个专用线程并使用它在循环中调用TextReader.Read()
:
process.Start();
new Thread(() =>
{
int ch;
while ((ch = process.StandardOutput.Read()) >= 0)
{
// process character...for example:
Console.Write((char)ch);
}
}).Start();
process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );
恕我直言后者更有效率,因为它不需要那么多的跨线程同步。但前者更类似于OutputDataReceived
事件所采用的事件驱动方法。