在 C# 中读取另一个 exe 的控制台挂起 UI

本文关键字:控制台 挂起 UI exe 另一个 读取 | 更新日期: 2023-09-27 18:34:34

我正在逐行读取 C# 项目中另一个 exe 的控制台,该项目成功读取了控制台的每一行,但我面临的问题是当 exe 开始执行我的 C# 表单时挂起并等待直到外部 exe 未完全执行。

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = EXELOCATION;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = argv;
startInfo.RedirectStandardOutput = true;
try
{
    // Start the process with the info we specified.
    // Call WaitForExit and then the using statement will close.
    using (exeProcess = Process.Start(startInfo))
    {
        using (StreamReader reader = exeProcess.StandardOutput)
        {
            string result;
            while ((result = reader.ReadLine() ) != null)
            {                            
                scanning.Text = result;
                scanning.Refresh();
                Console.Write(result);
            }
        }
    }

应该如何解决这个问题,请指导我

在 C# 中读取另一个 exe 的控制台挂起 UI

您可以使用

Process.OutputDataReceived(MSDN(

它允许附加一个事件处理程序,只要数据可用,就会调用该处理程序。

using (exeProcess = Process.Start(startInfo))
{
    exeProcess.OutputDataReceived +=
        (sender, args) =>
            {
                scanning.Text = args.Data;
                scanning.Refresh();
                Console.Write(args.Data);
            };
    exeProcess.BeginOutputReadLine();
    // do whatever you want here
    exeProcess.WaitForExit();
}

无论如何,如果您在 UI 线程中执行此操作,它仍然会阻止 UI。

另外,如果要从另一个线程更新 UI 控件的内容,则应调用 BeginInvoke()

在这种情况下,BackgroundWorker是一个很好的帮助。它将为您创建后台线程;并且可以安全地更新 ProgressChanged 事件处理程序中的 UI。

你应该使用 BackgroundWorker。

使用后台工作者:

以下是使用后台工作者的最少步骤:

  • 实例化 BackgroundWorker 并处理 DoWork 事件。
  • 调用 RunWorkerAsync,可以选择使用对象参数。

然后启动它。传递给 RunWorkerAsync 的任何参数都将通过事件参数的 Argument 属性转发到 DoWork 的事件处理程序。下面是一个示例:

class Program
{
  static BackgroundWorker _bw = new BackgroundWorker();
  static void Main()
  {
    _bw.DoWork += bw_DoWork;
    _bw.RunWorkerAsync ("Message to worker");
    Console.ReadLine();
  }
  static void bw_DoWork (object sender, DoWorkEventArgs e)
  {
    // This is called on the worker thread
    Console.WriteLine (e.Argument);        // writes "Message to worker"
    // Perform time-consuming task...
  }
}

我建议学习线程。最好和最简单的入门方法是 WinForms 中的后台辅助角色类。

但是你也应该看看 System.Threading 命名空间。

如果您在单个阻塞线程中执行所有操作,那么您的应用程序将不得不等到另一个 exe 将控制权返回到您的表单。

解决方案是在单独的线程中进行读取,这会在信息可用时将信息传递回应用程序。这稍微复杂一些,但并不难做到 - 您应该阅读可用的线程类,例如后台工作线程。