Csharp/C#教程:如何以线程安全的方式将控制台程序的输出重定向到文本框?分享


如何以线程安全的方式将控制台程序的输出重定向到文本框?

我无法将控制台输出重定向到Windows窗体文本框。 问题与线程有关。 我正在以下列方式运行控制台应用程序,

private void RunConsoleApp() { Process proc = new Process(); proc.StartInfo.FileName = "app.exe"; proc.StartInfo.Arguments = "-a -b -c"; proc.StartInfo.UseShellExecute = false; // set up output redirection proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.EnableRaisingEvents = true; proc.StartInfo.CreateNoWindow = true; // Set the data received handlers proc.ErrorDataReceived += proc_DataReceived; proc.OutputDataReceived += proc_DataReceived; proc.Start(); proc.BeginErrorReadLine(); proc.BeginOutputReadLine(); proc.WaitForExit(); if (proc.ExitCode == 0) { out_txtbx.AppendText("Success." + Environment.NewLine); } else { out_txtbx.AppendText("Failed." + Environment.NewLine); } } 

然后使用此输出处理程序捕获和处理数据,

 // Handle the date received by the console process void proc_DataReceived(object sender, DataReceivedEventArgs e) { if (e.Data != null) { if ((e.Data.EndsWith("DONE.")) || (e.Data.EndsWith("FAILED.")) || (e.Data.StartsWith("RESET"))) { // This crashes the application, but is supposedly the correct method this.AppendText(e.Data + Environment.NewLine); // This works, but the debugger keeps warning me that the call // is not thread safe //out_txtbx.AppendText(e.Data + Environment.NewLine); } } } 

然后像这样附加控制台文本,

 delegate void AppendTextDelegate(string text); // Thread-safe method of appending text to the console box private void AppendText(string text) { // Use a delegate if called from a different thread, // else just append the text directly if (this.out_txtbx.InvokeRequired) { // Application crashes when this line is executed out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), new object[] { text }); } else { this.out_txtbx.AppendText(text); } } 

从我看到的所有文档和示例看来,这似乎是正确的方法,除了它在调用out_txtbx.Invoke时崩溃应用程序。

什么可以被打破,有什么替代方法可以做到这一点?


解决方案 (Hans Passant指出)

问题是由于线路,应用程序陷入了“致命的拥抱”,

 proc.WaitForExit(); 

该行应删除,方法应如下所示,

 private void RunConsoleApp() { Process proc = new Process(); proc.StartInfo.FileName = "app.exe"; proc.StartInfo.Arguments = "-a -b -c"; proc.StartInfo.UseShellExecute = false; // set up output redirection proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.EnableRaisingEvents = true; proc.StartInfo.CreateNoWindow = true; // Set the data received handlers proc.ErrorDataReceived += proc_DataReceived; proc.OutputDataReceived += proc_DataReceived; // Configure the process exited event proc.Exited += new EventHandler(ProcExited); proc.Start(); proc.BeginErrorReadLine(); proc.BeginOutputReadLine(); // This blocks the main thread and results in "deadly embrace" // The Process.Exited event should be used to avoid this. //proc.WaitForExit(); } 

并应提供事件处理程序,

 ///  /// Actions to take when console process completes ///  private void ProcExited(object sender, System.EventArgs e) { Process proc = (Process)sender; // Wait a short while to allow all console output to be processed and appended // before appending the success/fail message. Thread.Sleep(40); if (proc.ExitCode == 0) { this.AppendText("Success." + Environment.NewLine); ExitBootloader(); } else { this.AppendText("Failed." + Environment.NewLine); } proc.Close(); } 

 proc.WaitForExit(); 

它被称为死锁。 您的主线程被阻止,等待进程退出。 这使它无法履行基本职责。 就像保持UI更新一样。 并确保调度Control.Invoke()请求。 这会阻止AppendText()方法完成。 这会停止退出的过程。 这会阻止您的UI线程通过WaitForExit()调用。 “致命的拥抱”,又名死锁。

你不能阻止你的主线程。 请改用Process.Exited事件。

尝试

上述就是C#学习教程:如何以线程安全的方式将控制台程序的输出重定向到文本框?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), text); 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/987649.html

(0)
上一篇 2021年12月23日
下一篇 2021年12月23日

精彩推荐