SwingWorker与FileVisitor不能快速发布处理过的信息; GUI挂起

时间:2015-08-20 16:24:01

标签: java swing swingworker filevisitor

使用SwingWorker FileVisitor不快速发布已处理的信息; GUI挂起。我希望它没有,希望帮助解决这个问题

以下是我如何使用SwingWorkerFileVisitor接口在Windows目录节点中搜索符合用户指定条件的文件的简要概述。 :

  public class Main 
  {
    public static void main(String args[]) 
    {
      EventQueue.invokeLater( new Runnable() {
          @Override public void run() {
            gui = new GUI();
          }});
    }
  }
  //==============================================================
  public class GUI extends JFrame
  {
    public     GUI()
    {
      init();
      createAndShowGUI();
    }

     private void init()
     {
       dftTableModel = new DefaultTableModel(0 , 4);
         tblOutput     = new JTable(dftTableModel);
         tblOutput.setAutoResizeMode(AUTO_RESIZE_OFF);
         scrTblOutput     = new JScrollPane(tblOutput);
       dftTableModel.setColumnIdentifiers(new Object[]{"Date", "Size", "Filename", "Path"});

编辑我只包含这两条线,问题可能已经解决了

       tca = new tablecolumnadjuster.TableColumnAdjuster(tblOutput);
       tca.setDynamicAdjustment(true);

     }

      private static void btnSearchActionPerformed(ActionEvent evt) 
      {
        TASK task = new TASK();
        task.execute();      
      }
    }
  }
  //==============================================================

  public class TASK extends SwingWorker<Void,String>
  {

    private class rowRec{
      String date;
      int size;
      String filename;
      String pathname;

      private rowRec(String d, int s, String f, String p) 
      {
        date = d; 
        size = s; 
        filename = f; 
        pathname = p;
      }
    }

    FV fv;

    TASK() {        fv = new FV();        }

    //-------------- inner class   

      class FV implements FileVisitor<Path>
      {
        // When walk begins, internal FileVisitor code makes this routine
        // loop until no more files are found OR disposition = TERMINATE.

        public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException 
        {
          if(f.getFileName().toString().toLowerCase().matches(fPatt.toLowerCase().trim()))
          {

             publish(s); 

             if(++k > parseInt(GUI.txtMaxMatches.getText()))

                disposition = TERMINATE;
                publish("Stopped at max. records specified");
          }
          return disposition;
        }
      }
    //----------------

    private  void report(String s)
    {
      rowData = new rowRec(date, isize, filename, path);
      dftTableModel.addRow(new Object[]{rowData.date, rowData.size, rowData.filename, rowData.pathname});
    }

    @Override
    protected void process(List<String> chunks)
    {
      chunks.stream().
        forEach
        (
           (chunk) -> 
           {
             report(chunk);
           }
      );
      kc += chunks.size();
      System.out.println(kc); // *********************************
    }

    @Override
    public Void doInBackground() throws Exception 
    {
        disposition = FileVisitResult.CONTINUE;
        Files.walkFileTree(GUI.p ,fv);
    }
  }

GUI启动SwingWorker的新实例,其作用是显示JTable实例找到的TASK文件信息。 TASK实例化FileVisitorwalkFileTree开始。 visitFile方法中找到的每个匹配文件publishSwingWorkerprocess

它在大多数情况下都很有效,但是如果有大量匹配的文件,GUI会在几秒钟内无响应;同时,已经发生了大量的阅读和显示,并且每隔几千个文件读取就会更新UI。

尽管在背景中使用SwingWorker来填充JTable,显然(我猜是)太多匹配的文件信息来得太快而无法跟上。

这就是我说的原因:

即使visitFile有一个向TERMINATE发出信号的计数器,但process显然远远落后于向JTable添加记录。其中的println表示,随着时间的推移,chunks传递的数量会有很大差异,具体取决于FileVisitor查找匹配率:

41
81
138
250
604
1146
...
1417
1497
1590
1670
1672
1676
1680
1682
1692
1730
1788
1794
1797
1801
1807
1820
1826
1829
1847
1933
2168
10001

visitFile终止后,process必须向JTable发送(10001-2168)或7833条记录,这需要很长时间,并且GUI没有响应时间。事实上,如果最大。匹配是(荒谬的)10,000,该程序挂起很多MINUTES,但是JTable中有10,000个记录。

我不知道如何处理无响应。我希望能够点击STOP按钮让程序停止。或者能够X(关闭)窗口。没办法。

我没有正确使用SwingWorker吗?我无法让树步行基于SwingWorker,因为我没有可用的循环(它是内部的) )。

P.S。虽然显然是挂起的,javaw占用了25%的CPU时间并且每秒增加大约16K的内存分配,因为process一直在下去,直到它最终发布最后一个块。

enter image description here

修改

我可能找到了帮助here

但是,gee, 关闭 ??

我突出了我的问题。

2 个答案:

答案 0 :(得分:2)

我不知道你的问题的解决方案,但我知道这不应该在SwingWorker或其内部类中完成:

GUI.txtMaxMatches.getText())

您应该在EDT上获取此信息,并通过其构造函数将其传递给SwingWorker。

答案 1 :(得分:0)

响应问题在一行代码中得到解决。

// tca.setDynamicAdjustment(true);

请参阅原始问题中的编辑。