我正在编写一个 java swt 应用程序来处理服务器日志文件并生成带有一些分析的 Excel 工作表,我这样做没有任何问题。
当我尝试更新进度条时出现问题。
这是代码的基本流程。用户使用目录对话框选择日志文件并按下开始按钮。单击按钮时,将执行以下代码。
startButton.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
pm.setUserData(ud,progressBar);
progressBar.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
pm.startProcessing();
}
});
}
在实际处理文件的类中,有一个简单的 while 循环,一直循环到到达文件末尾。从文件中读取每一行后,我调用一个更新进度条的方法。
while ((logEntry = br.readLine()) != null) {
readSize += logEntry.length() + 1;
//some long processing logic
progressBar.setSelection(getProgress());
}
getProgress() 是一个计算文件读取百分比的简单方法
(read/total)*100
上面的程序正在运行。我得到了预期的结果。进度条更新,但 GUI 变得无响应。我无法移动窗户。我无法点击关闭按钮。
我尝试使用 Swing Worker 和 display.asyncExec()
ProgressBar.setSelection()
当未从 UI 线程调用时,将抛出异常 (ERROR_THREAD_INVALID_ACCESS
)。这意味着您要么在代码中的某个地方吞下异常,要么上面的代码在 UI 线程中运行。
有一个 片段展示了如何从线程更新
ProgressBar
:
display.asyncExec(new Runnable() {
@Override
public void run() {
if (bar.isDisposed ())
return;
bar.setSelection(getProgress);
}
});
我用不同的实现来解决相同的问题或想法,使用执行器服务,非常基本并且可以控制。
ScheduledExecutorService timer =
Executors.newSingleThreadScheduledExecutor();
Runnable work = new Runnable() {
public void run() {
try {
int currentPercent = externalAsyncService.getCurrentPercentReport();
display.asyncExec(() - > progressBarReportStatus.setSelection(currentPercent));
if (currentPercent >= 100) {
timer.shutdown();
}
} catch (Exception e) {
LOG.error(e.toString());
}
}
};
timer.scheduleAtFixedRate(work, 1, 5, TimeUnit.SECONDS);