C# 等待所有日期重定向
C# Wait for all dates from redirecting
我正在将我的进程 (proc) 的输出重定向到 richtextbox (richTextBoxOutput)。在重定向之前,它写入richtextbox句子"BEFORE OUTPUT DATA"。然后它应该写入进程中的所有数据,并在 之后写入句子 "AFTER OUTPUT DATA"。但是,这最后一句话永远不会结束。它总是在重定向日期之间的 richtextbox 中间的某个地方。你能帮我解决一下吗?
richTextBoxOutput.AppendText("BEFORE OUTPUT DATA");
Process proc = new Process();
proc.StartInfo.FileName = command;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.OutputDataReceived += new DataReceivedEventHandler
(
(s, e) =>
{
if (richTextBoxOutput.InvokeRequired)
{
richTextBoxOutput.Invoke(new Action(() => richTextBoxOutput.AppendText(e.Data + "\n")));
}
else
richTextBoxOutput.AppendText(e.Data + "\n");
}
);
proc.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { richTextBoxOutput.AppendText(e.Data + "\n"); });
proc.Start();
proc.BeginOutputReadLine();
while (!proc.HasExited)
{
Application.DoEvents(); //Instead of proc.WaitForExit()
}
richTextBoxOutput.AppendText("AFTER OUTPUT DATA");
我可以建议一个异步方法来解决这个问题吗?
是的,您将不得不处理跨线程调用,因为您正在从另一个线程写入 windows 表单(类似文本框)组件,但好的部分是您可以使用 proc.WaitForExit
而不必担心冻结界面(没有那个非常无效的讨厌循环,因为它会让你的应用程序烧毁 CPU)并且有一个 ContinueWith
子句来附加你的 "AFTER OUTPUT DATA"!
最小工作样本:
private void btnRun_Click(object sender, EventArgs e) {
Task.Factory.StartNew(this.StdOutWorker);
}
private void StdOutWorker() {
this.AppendLine("BEFORE OUTPUT DATA");
// "CmdRandomGenerator.exe" will print random numbers to standard output in infinity loop
ProcessStartInfo pi = new ProcessStartInfo("CmdRandomGenerator.exe") {
RedirectStandardOutput = true,
UseShellExecute = false
};
var proc = new Process{
StartInfo = pi,
EnableRaisingEvents = true
};
proc.Start();
while (!proc.HasExited) {
var line = proc.StandardOutput.ReadLine();
this.AppendLine(line);
}
this.AppendLine("AFTER OUTPUT DATA");
}
private void AppendLine(string line) {
Action act = () => {
this.rtbOutput.AppendText(line + Environment.NewLine);
};
// UI objects must be accessed in UI thread
this.BeginInvoke(act);
}
想法是,从进程中读取是在后台线程中进行的,并且将值传递给 UI 线程而不等待结果(即发即弃)。
理论上,来自观察过程的值可能会比 UI 可以处理的更快。在那种情况下,您必须丢弃一些值(采样)。
但是我尝试使用 while(true) { Console.WriteLine(random()); }
并且 UI 速度较慢但仍然响应。
我正在将我的进程 (proc) 的输出重定向到 richtextbox (richTextBoxOutput)。在重定向之前,它写入richtextbox句子"BEFORE OUTPUT DATA"。然后它应该写入进程中的所有数据,并在 之后写入句子 "AFTER OUTPUT DATA"。但是,这最后一句话永远不会结束。它总是在重定向日期之间的 richtextbox 中间的某个地方。你能帮我解决一下吗?
richTextBoxOutput.AppendText("BEFORE OUTPUT DATA");
Process proc = new Process();
proc.StartInfo.FileName = command;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.OutputDataReceived += new DataReceivedEventHandler
(
(s, e) =>
{
if (richTextBoxOutput.InvokeRequired)
{
richTextBoxOutput.Invoke(new Action(() => richTextBoxOutput.AppendText(e.Data + "\n")));
}
else
richTextBoxOutput.AppendText(e.Data + "\n");
}
);
proc.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { richTextBoxOutput.AppendText(e.Data + "\n"); });
proc.Start();
proc.BeginOutputReadLine();
while (!proc.HasExited)
{
Application.DoEvents(); //Instead of proc.WaitForExit()
}
richTextBoxOutput.AppendText("AFTER OUTPUT DATA");
我可以建议一个异步方法来解决这个问题吗?
是的,您将不得不处理跨线程调用,因为您正在从另一个线程写入 windows 表单(类似文本框)组件,但好的部分是您可以使用 proc.WaitForExit
而不必担心冻结界面(没有那个非常无效的讨厌循环,因为它会让你的应用程序烧毁 CPU)并且有一个 ContinueWith
子句来附加你的 "AFTER OUTPUT DATA"!
最小工作样本:
private void btnRun_Click(object sender, EventArgs e) {
Task.Factory.StartNew(this.StdOutWorker);
}
private void StdOutWorker() {
this.AppendLine("BEFORE OUTPUT DATA");
// "CmdRandomGenerator.exe" will print random numbers to standard output in infinity loop
ProcessStartInfo pi = new ProcessStartInfo("CmdRandomGenerator.exe") {
RedirectStandardOutput = true,
UseShellExecute = false
};
var proc = new Process{
StartInfo = pi,
EnableRaisingEvents = true
};
proc.Start();
while (!proc.HasExited) {
var line = proc.StandardOutput.ReadLine();
this.AppendLine(line);
}
this.AppendLine("AFTER OUTPUT DATA");
}
private void AppendLine(string line) {
Action act = () => {
this.rtbOutput.AppendText(line + Environment.NewLine);
};
// UI objects must be accessed in UI thread
this.BeginInvoke(act);
}
想法是,从进程中读取是在后台线程中进行的,并且将值传递给 UI 线程而不等待结果(即发即弃)。
理论上,来自观察过程的值可能会比 UI 可以处理的更快。在那种情况下,您必须丢弃一些值(采样)。
但是我尝试使用 while(true) { Console.WriteLine(random()); }
并且 UI 速度较慢但仍然响应。