SwingWorker с FileVisitor не публикует обработанную информацию быстро; GUI зависает
С помощью 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
Эд для SwingWorker
в process
,
Он прекрасно работает большую часть времени, но если имеется множество подходящих файлов, графический интерфейс пользователя перестает отвечать на запросы в течение нескольких секунд; тем временем произошло много чтения и отображения, а пользовательский интерфейс обновляется каждые несколько тысяч операций чтения файлов.
Несмотря на использование 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
пришлось отправить (10001-2168) или 7833 записей на JTable
и это заняло много времени, и GUI оставался без ответа большую часть времени. На самом деле, если макс. совпадений (нелепо) 10 000, программа зависает в течение многих МИНУТ, но 10 000 записей находятся в JTable
,
Я не знаю, что делать с неотзывчивостью. Я хотел бы иметь возможность нажать кнопку СТОП и остановить программу. Или быть в состоянии X
(закрыть) окно. Ни за что.
Я не использую SwingWorker
правильно? Я не могу заставить дерево ходить основываться на SwingWorker
поскольку у меня нет петли, доступной мне (она внутренняя).
PS пока видимо зависла, javaw
занимает 25% процессорного времени и увеличивает выделение памяти примерно на 16 КБ в секунду, как process
бродит, пока наконец не публикуется последний кусок.
РЕДАКТИРОВАТЬ
Я мог бы найти помощь здесь.
Но, блин, близко?
Я выделил свои вопросы.
2 ответа
Проблема отзывчивости решается в ОДНОЙ СТРОКЕ.
// tca.setDynamicAdjustment(true);
Обратитесь к редактированию в оригинальном вопросе.
Я не знаю решения вашей проблемы, но я знаю, что этого не следует делать внутри SwingWorker или его внутренних классов:
GUI.txtMaxMatches.getText())
Вы должны получить эту информацию в EDT и передать ее в ваш SwingWorker через его конструктор.