简体   繁体   English

调用SwingWorker.get()时防止GUI冻结

[英]Preventing GUI From Freezing When Calling SwingWorker.get( )

I have a program where I am loading a file while at the same time I am displaying a window to inform the user that the file is being loaded. 我有一个程序,我正在加载一个文件,同时我正在显示一个窗口,通知用户该文件正在加载。 I decided to make a FileLoader class that was a SwingWorker which actually handled loading the file and a ProgressWindow that implements PropertyChangeListener to inform the user about the status of the SwingWorker that was passed into it. 我决定创建一个FileLoader类,它实际上是处理文件的SwingWorker和实现PropertyChangeListener的ProgressWindow,以通知用户传递给它的SwingWorker的状态。

My code currently looks like this: 我的代码目前看起来像这样:

FileLoader loader = new FileLoader(filePath);
new ProgressWindow(loader, "Loading File", "Loading File");
//ProgressWindow's constructor calls loader.execute() inherited from SwingWorker
doc = loader.get(); //GUI Freezes when called

The problem is that whenever I call loader.get(), it freezes the GUI, thus the progress bar in the Progress Window doesn't run and the whole thing is pointless. 问题是,无论何时我调用loader.get(),它都会冻结GUI,因此进度窗口中的进度条不会运行,整个过程毫无意义。 As far as I can tell, this is because the thread controlling the GUI is the same thread that calls loader.get(), which goes on hold while loader.execute() is running. 据我所知,这是因为控制GUI的线程与调用loader.get()的线程相同,而loader.get()在loader.execute()运行时保持不变。

So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes. 到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。

I've considered creating a ChangeListener for when SwingWorker.isDone() and then running loader.get(), but this would require some reworking of my code that I would rather not do. 我考虑过为SwingWorker.isDone()创建一个ChangeListener,然后运行loader.get(),但是这需要对我的代码进行一些修改,而我宁愿不做。

Could anyone tell me what the best way is to get this to work? 谁能告诉我最好的方法是让它发挥作用?

get() is like join() in that it will block until called, and will wait for the SwingWorker to finish before being called. get()就像join()一样,它会一直阻塞直到被调用,并等待SwingWorker在被调用之前完成。 Using it wrongly can completely nullify all the advantages of using a SwingWorker in the first place. 错误地使用它可以完全取消使用SwingWorker的所有优点。

Solution: Don't call get() until you know that the SwingWorker is done with its processing, by either calling it in the SwingWorker's done() method, or if you need to call it from the calling code, then in a PropertyChangeListener that has been added to the SwingWorker when the SwingWorker's "state" property is SwingWorker.StateValue.DONE. 解决方案:在您知道SwingWorker完成其处理之前,通过在SwingWorker的done()方法中调用它,或者如果您需要从调用代码调用它,然后在PropertyChangeListener中调用它,请不要调用get() 。当SwingWorker的“state”属性为SwingWorker.StateValue.DONE时,已添加到SwingWorker中。

Something like: 就像是:

  final FileLoader loader = new FileLoader(filePath);

  loader.addPropertyChangeListener(new PropertyChangeListener() {
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        if ("state".equals(evt.getPropertyName())) {
           // since DONE is enum, no need for equals(...) method
           if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
              try {
                 loader.get();
              } catch (InterruptedException e) {
                 e.printStackTrace();
              } catch (ExecutionException e) {
                 e.printStackTrace();
              }
           }
        }
     }
  });

  new ProgressWindow(loader, "Loading File", "Loading File");

Note: code not compiled nor tested 注意:代码未编译也未经过测试

Edit: try/catch added. 编辑:尝试/捕获添加。

So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes. 到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。

If you call SwingUtilities.invokeLater() on the thread that will execute the thread in the EDT which freezes the GUI. 如果在将执行EDT中冻结GUI的线程的线程上调用SwingUtilities.invokeLater() Instead, run the thread by calling it's start() method and only use SwingUtilities.invokeLater() when you need to update the progress bar in the PropertyChangeListener . 相反,通过调用它的start()方法运行该线程,并在需要更新PropertyChangeListener的进度条时仅使用SwingUtilities.invokeLater()

I have create a WorkerThread class which take care of Threads and GUI current/main thread . 我已经创建了一个WorkerThread类来处理Threads和GUI current / main thread。 i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. 我已经将我的GUI应用程序放在WorkerThread的construct()方法中,当一个事件触发启动XXXServer然后所有线程都被激活并且GUI工作平稳地没有冻结。 have a look. 看一看。

/**
* Action Event
* 
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent ae) {
    log.info("actionPerformed begin..." + 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());
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM