带有 FileVisitor 的 SwingWorker 不能快速发布处理过的信息; GUI 挂起
SwingWorker with FileVisitor not publishing processed info quickly; GUI hangs
使用 SwingWorker
和 FileVisitor
不能快速发布处理过的信息; GUI挂起。我宁愿它没有,想帮助解决这个问题。
这里简要介绍了我如何使用 SwingWorker
和 FileVisitor
界面来搜索 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
实例化 FileVisitor
,walkFileTree
开始。在 visitFile
方法中找到的每个匹配文件都被 publish
ed 为 SwingWorker
到 process
.
大部分时间都很好用,但如果有大量匹配文件,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,程序挂起很多分钟,但是 JTable
.
中有 10,000 条记录
我不知道如何处理无响应。我希望能够点击“停止”按钮让程序停止。或者能够X
(关闭)window。没办法。
我没有正确使用 SwingWorker
吗? 我不能让树行走基于 SwingWorker
因为没有可用的循环对我来说(它是内部的)。
P.S。虽然显然挂起,但 javaw
占用了 CPU 的 25% 的时间,并以每秒约 16K 的速度增加其内存分配,因为 process
缓慢进行,直到它最终发布最后一个块。
编辑
我可能找到了帮助 here。
但是,哎呀,关闭??
我已经突出显示了我的问题。
我不知道你的问题的解决方案,但我知道这不应该在 SwingWorker 或其内部完成 类:
GUI.txtMaxMatches.getText())
您应该在 EDT 上获取此信息并通过其构造函数将其传递到您的 SwingWorker。
一行代码解决了响应问题。
// tca.setDynamicAdjustment(true);
参考原始问题中的编辑。
使用 SwingWorker
和 FileVisitor
不能快速发布处理过的信息; GUI挂起。我宁愿它没有,想帮助解决这个问题。
这里简要介绍了我如何使用 SwingWorker
和 FileVisitor
界面来搜索 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
实例化 FileVisitor
,walkFileTree
开始。在 visitFile
方法中找到的每个匹配文件都被 publish
ed 为 SwingWorker
到 process
.
大部分时间都很好用,但如果有大量匹配文件,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,程序挂起很多分钟,但是 JTable
.
我不知道如何处理无响应。我希望能够点击“停止”按钮让程序停止。或者能够X
(关闭)window。没办法。
我没有正确使用 SwingWorker
吗? 我不能让树行走基于 SwingWorker
因为没有可用的循环对我来说(它是内部的)。
P.S。虽然显然挂起,但 javaw
占用了 CPU 的 25% 的时间,并以每秒约 16K 的速度增加其内存分配,因为 process
缓慢进行,直到它最终发布最后一个块。
编辑
我可能找到了帮助 here。
但是,哎呀,关闭??
我已经突出显示了我的问题。
我不知道你的问题的解决方案,但我知道这不应该在 SwingWorker 或其内部完成 类:
GUI.txtMaxMatches.getText())
您应该在 EDT 上获取此信息并通过其构造函数将其传递到您的 SwingWorker。
一行代码解决了响应问题。
// tca.setDynamicAdjustment(true);
参考原始问题中的编辑。