Java Swing多线程和UI冻结

3

无法弄清楚这个问题。即使使用 worker 或 invokeLater,UI 仍然会冻结。每次下载完文件后,我想要更新一个 JList。但是 JList 只会在线程返回之后更新。

以下是代码:

public class MyUi extends javax.swing.JFrame{
    ...

   private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){

      SwingUtilities.invokeLater(new Runnable() {
         //To get out of the event tread
         public void run() {
            dl(); 
         }
       });
   }

   private void dl(){
      ...
      //ini and run the download class
      Download myDownload = new Download();
      myDownload.doDownload(myDlList);
   }

   public void updateJlist(String myString){

       myModel.addElement(myString);
       jList1.repaint();
   }

}

public class Download{
...

  public void doDownload(String[] fileName){
      for(int i=0; i<fileName.length; i++){
         ...//download action...
         //for my jList1 to be updated after each file.
         MyUi.updateJlist(fileName[i]);
      }
   }

}

任何示例都有助于理解。
3个回答

4

invokeLater执行的是与预期相反的操作——它在EDT上运行操作,这解释了其行为。


3
在后台线程上下载文件,并将updateJlist()放入Runnable中。建议使用SwingWorker,它更加可靠。
补充说明:如@mre所述,SwingWorker还可以轻松报告中间结果,示例请参见此处

在后台运行下载很好用,我不需要包装updateJlist()。对于SwingWorker,我需要再多读一些资料并进行测试。我还没有完全理解它。谢谢! - marcb
我很高兴它正在工作,但我仍然对从非EDT线程更新GUI持谨慎态度。如果您需要使用SwingWorker的帮助,请随时发布问题。 - trashgod
1
@marcb,即使它现在看起来工作正常,更新EDT列表只是完全错误的。您必须在EDT上访问所有Swing组件的属性(包括任何模型),没有例外。 - kleopatra
我已经删除了我的评论“最终代码:”,因为我现在意识到即使它完美地工作,这是一个巨大的错误和糟糕的编码。我将继续阅读SwingWorker,清理我的代码,然后再发布我的问题和关注点。感谢您的支持。 - marcb

0

我创建了一个WorkerThread类,它负责线程和GUI当前/主线程。我将我的GUI应用程序放在WorkerThread的construct()方法中,当事件触发启动XXXServer时,所有线程都被激活,GUI可以平稳地工作而不会冻结。看一下。

/** * Action Event * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */

public void actionPerformed(ActionEvent ae) { log.info("actionPerformed开始..." + ae.getActionCommand());

try {
    if (ae.getActionCommand().equals(btnStart.getText())) {
         final int portNumber = 9990;
         try {

             WorkerThread workerThread = new WorkerThread(){
                public Object construct(){

                    log.info("Initializing the Server GUI...");
                    // initializing the Server
                     try {
                        xxxServer = new XXXServer(portNumber);
                        xxxServer.start();
                        btnStart.setEnabled(false);                             
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
                        e.printStackTrace();
                    }
                    return null;
                }
            };workerThread.start();
            } catch (Exception e) {
                log.info("actionPerformed() Start button ERROR..." + e.getMessage());
                e.printStackTrace();
         }


    } else if (ae.getActionCommand().equals(btnStop.getText())) {
        log.info("Exit..." + btnStop.getText());
        closeWindow();
    }

} catch (Exception e) {
    log
        .info("Error in ServerGUI actionPerformed==="
            + e.getMessage());
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接