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

Thu*_*rge 3 java swing swingworker

我有一个程序,我正在加载一个文件,同时我正在显示一个窗口,通知用户该文件正在加载.我决定创建一个FileLoader类,它实际上是处理文件的SwingWorker和实现PropertyChangeListener的ProgressWindow,以通知用户传递给它的SwingWorker的状态.

我的代码目前看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

问题是,无论何时我调用loader.get(),它都会冻结GUI,因此进度窗口中的进度条不会运行,整个过程毫无意义.据我所知,这是因为控制GUI的线程与调用loader.get()的线程相同,而loader.get()在loader.execute()运行时保持不变.

到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结.

我考虑过为SwingWorker.isDone()创建一个ChangeListener,然后运行loader.get(),但是这需要对我的代码进行一些修改,而我宁愿不做.

谁能告诉我最好的方法是让它发挥作用?

Hov*_*els 6

get()就像join()在被调用之前它会阻塞一样,并且会在被调用之前等待SwingWorker完成.错误地使用它可以完全取消使用SwingWorker的所有优点.

解决方案:在get()您知道SwingWorker完成其处理之后,通过在SwingWorker的done()方法中调用它,或者您需要从调用代码调用它,然后在已添加到SwingWorker的PropertyChangeListener中,不要调用当SwingWorker的"state"属性是SwingWorker.StateValue.DONE时.

就像是:

  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");
Run Code Online (Sandbox Code Playgroud)

注意:代码未编译也未经过测试

编辑:尝试/捕获添加.