0

我在使用 时遇到问题,JFrame在连续运行代码时会冻结。下面是我的代码:

  1. 单击时btnRun,我调用了该函数MainLoop()

    ActionListener btnRun_Click = new ActionListener() {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            MainLoop();
        }
    };
    
  2. 实施MainLoop()

    void MainLoop()
    {
        Hopper = new CHopper(this);
        System.out.println(Hopper);
        btnRun.setEnabled(false);
        textBox1.setText("");
        Hopper.getM_cmd().ComPort = helpers.Global.ComPort;
        Hopper.getM_cmd().SSPAddress = helpers.Global.SSPAddress;
        Hopper.getM_cmd().Timeout = 2000;
        Hopper.getM_cmd().RetryLevel = 3;
    
    
        System.out.println("In MainLoop: " + Hopper);
    
        // First connect to the validator
        if (ConnectToValidator(10, 3))
        {
            btnHalt.setEnabled(true);
            Running = true;
    
            textBox1.append("\r\nPoll Loop\r\n"
                    + "*********************************\r\n");
        }
    
        // This loop won't run until the validator is connected
        while (Running)
        {
            // poll the validator
            if (!Hopper.DoPoll(textBox1))
            {
                // If the poll fails, try to reconnect
                textBox1.append("Attempting to reconnect...\r\n");
                if (!ConnectToValidator(10, 3))
                {
                    // If it fails after 5 attempts, exit the loop
                    Running = false;
                }
            }
            // tick the timer
                    // timer1.start();
            // update form
            UpdateUI();
            // setup dynamic elements of win form once
            if (!bFormSetup)
            {
                SetupFormLayout();
                bFormSetup = true;
            }
    
        }
    
        //close com port
        Hopper.getM_eSSP().CloseComPort();
    
        btnRun.setEnabled(true);
        btnHalt.setEnabled(false);
    }
    
  3. MainLoop()函数中,while 循环一直在运行,直到 Running 为 true 问题是,如果我想停止该 while 循环,我必须将 Running 设置为 false,这是在另一个按钮上完成的btnHalt

    ActionListener btnHalt_Click = new ActionListener() {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            textBox1.append("Poll loop stopped\r\n");
            System.out.println("Hoper Stopped");
            Running = false;
        }
    };
    

btnHalt没有响应,整个框架被冻结,也没有显示任何日志textarea

4

1 回答 1

2

Swing 是一个单线程框架。也就是说,有一个线程负责将所有事件分派给所有组件,包括重绘请求。

任何停止/阻止此线程的操作都会导致您的 UI “挂起”。

Swing 的第一条规则,永远不要在 Event Dispatching Thread 上运行任何阻塞或耗时的任务,而应该使用后台线程。

这会让你陷入 Swing 的第二条规则。切勿在 EDT 之外创建、修改或与任何 UI 组件交互。

有多种方法可以解决此问题。您可以使用SwingUtilities.invokeLaterSwingWorker.

SwingWorker通常更容易,因为它提供了许多简单易用的方法,可以自动重新同步对 EDT 的调用。

阅读Swing 中的并发

更新

只是让你明白;)

您的MainLoop方法不应该在 EDT 的上下文中执行,这非常糟糕。

此外,您不应与除 EDT 之外的任何线程中的任何 UI 组件进行交互。

于 2013-03-21T05:47:19.260 回答