【问题标题】:Running another process without GUI freezing运行另一个进程而不冻结 GUI
【发布时间】:2011-01-25 06:18:08
【问题描述】:

在运行(和等待)外部进程时,我无法让我的 GUI 出现并且不冻结。在这种情况下,drivers.exe 是一个非常简单的程序,用户只需单击“确定”即可。因此,每当我单击“确定”时,它就会退出。我正在尝试在执行 drivers.exe 时简单地增加我的状态条计数(非常快)。但实际上,在 drivers.exe 退出之前,我的 GUI 根本不会出现。

private void run_drivers()
        {
            Console.WriteLine("Start Driver");
            int driver_timeout_in_minutes = 20;
            System.Diagnostics.Process driverproc = System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "drivers.exe");
            driverproc.WaitForExit(driver_timeout_in_minutes * 1000 * 60);   //uses milliseconds, we must convert
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ThreadStart worker = new ThreadStart(run_drivers);
            Console.WriteLine("Main - Creating worker thread");
            toolStripStatusLabel1.Text = "hi";
            Thread t = new Thread(worker);
            t.IsBackground = true;
            t.Start();
            Console.WriteLine("Main - Have requested the start of worker thread");

            int i = 0;
            while (t.IsAlive)
            {
                i++;
                toolStripStatusLabel1.Text = i.ToString();
            }
            Console.WriteLine("Dead");
        }

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    您应该查看BackgroundWorker,因为它会为您完成所有线程工作

    【讨论】:

    • 你能告诉我怎么做吗?我确实试了一下,它真的一点用都没有。实际上,我的表单仍然不会显示...根本不显示。
    • 问题是“while(t.IsAlive)”循环。无论他是否使用 BackgroundWorker,他都需要将其从 UI 线程中移除。
    【解决方案2】:

    在drivers.exe 运行之前您的表单不显示的原因是因为您在Form.Load 中运行drivers.exe。 Form.Load 出现在表单显示之前。请尝试在 Form.Shown 中运行 drivers.exe。

    另外,while(t.IsAlive) 在技术上会阻塞你的 UI 线程。如果那不是您想要的,则应将其移出主线程。您可能还需要调用toolStripStatusLabel1.Refresh() 以在设置文本后强制刷新标签。

    【讨论】:

    • 无论代码运行在Form.Load还是更高版本,UI线程在执行时仍然没有时间绘制屏幕,​​如图所示。
    【解决方案3】:

    不要在 GUI 线程上放置任何循环。它会冻结你的应用程序。循环必须在后台线程上,该线程应该通过Invoke 方法更新toolStripStatusLabel1

    见这个例子。未经测试。也许它甚至可以像这样工作......

        private void run_drivers()
        {
            Console.WriteLine("Start Driver");
            int driver_timeout_in_minutes = 20;
            System.Diagnostics.Process driverproc = System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "drivers.exe");
            int i = 0;
            var action = new Action<int>(x => {  toolStripStatusLabel1.Text = i.ToString(); })
            while (!driverproc.HasExited)
            {
                i++;
                toolStripStatusLabel1.Invoke(action);
            }
    
            Console.WriteLine("Dead");
            // start another thread here...
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            ThreadStart worker = new ThreadStart(run_drivers);
            Console.WriteLine("Main - Creating worker thread");
            toolStripStatusLabel1.Text = "hi";
            Thread t = new Thread(worker);
            t.IsBackground = true;
            t.Start();
            Console.WriteLine("Main - Have requested the start of worker thread");
        }
    

    【讨论】:

    • 好吧,这很有道理。但是,我如何等待执行一个功能,直到另一个功能完成?比如我想在func_2完成后才执行func_2,这两个都需要几分钟才能完成。
    • run_drivers()方法的最后一行开始新线程。远离 GUI 线程上的循环。
    【解决方案4】:

    在保留当前代码结构的同时,您可以使用的一种解决方案是在 timer 线程上定期更新 UI,并在线程完成时停止计时器。这样做,您将从循环更改为事件驱动设计,并且您将给 UI 线程时间来绘制您的表单。

    // create a System.Windows.Forms.Timer through the designer or in code.
    // give it a short interval if you want the counter to increment quickly.
    
    int counter;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        ...
        t.Start();
        counter = 0;
        timer.Start();
        ....
    }
    
    private void timer_Tick(object sender, EventArgs e)
    {
       if (t.IsAlive)
       {
           counter++;
           toolStripStatusLabel1.Text = counter.ToString(); 
       }
       else
       {
          timer.Stop();
       }
    }
    

    (未测试)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-07
      • 1970-01-01
      • 2013-10-31
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多