1

使用的技术: Java 1.6 SWT GUI

问题: 在后台任务运行大约 60 分钟后,GUI 信息更新最终会停止(GUI 完全没有响应)。

问题似乎与 GUI 更新有关,我无法弄清楚如何解决这种情况(查看了 Java 并发选项等)。优化线程使用处理信息定期更新 GUI 中的文本框。在我的测试过程中,这个“更新”明显落后于控制台输出和数据库输出——假设优化执行了 4000 个优化步骤。控制台可以报告优化步骤 1900 的工作(在数据库中确认),但 GUI 仍然输出来自步骤 700 的信息。

背景信息: 我正在运行机器学习优化任务并将该任务合并到 SWT GUI 中。该任务可能需要一个小时或更长时间才能完成,具体取决于参数。我将优化任务设计为一个单独的线程。GUI 允许用户按下按钮来启动优化。GUI 包括(为了简化)1)任务表和 2)优化期间用于反馈的 SWT 文本框。随着每个不同的任务组完成,任务表会更新。SWT 文本框输出更常规/频繁的反馈(很像System.out但使用线程通过 GUI EDI 线程更新文本框)。也就是说,我相信我至少使用了三个线程:1) GUI 线程,2)aSync用于 GUI 更新 (SWT) 的线程,以及 3) 用于优化本身的后台线程。(我提到这一点是因为 Java 并发教程明确指出长时间运行的任务必须在它们自己的线程中运行以避免 GUI 死锁和饥饿。然而,即使我认为我这样做了,在长时间的优化运行后 GUI 仍然停止——并且这就是我要解决的问题。因为优化运行需要很长时间才能完成,所以 GUI 停顿是一个主要问题——在意识到 GUI 停顿之前损失了一个多小时。)

基本程序结构: GUI类-->为优化类启动一个单独的线程

优化类可以通过回调更新 GUI 类组件(使用 SWT asyncExec

已确认: 我可以确认后台线程运行完全--1)后​​台线程更新了几个数据库表并且所有表都完全完全更新了;2)System.out直接从Eclipse中发送到控制台的优化任务的输出显示优化线程完全运行。

此外,在测试期间,如果我将优化设置缩减到 400 步,GUI 似乎运行良好。

相关代码: GUI CLASS——更新 GUI 和 GUI 类中的代码(由优化类线程调用)——

public void setFeedback(final String workerthreadinfo, final boolean append) {
try{  
    Display.getDefault().asyncExec(new Runnable(){  
    public void run(){  
        if(!textfeedback.isDisposed() && textfeedback !=null){  
        if (append) {
                      textfeedback.setText(workerthreadinfo + "\n" +
                            textfeedback.getText()) ;
        } else {
            textfeedback.setText(workerthreadinfo) ;
        }  
         } 
    }  
    });
     } .....

GUI 类中优化工作线程的实例化

private OptimizerWorkerThread workerthread = 
   new OptimizerWorkerThread(this) ;

GUI 类中的代码启动优化类(作为线程)

protected void optimize() {
    workerthread.go() ;
}

OPTIMIZATION CLASS--“链接”到 GUI 的优化线程方法(guiwindow = 上面的 GUI 类)

// ==================================================================
// GUI Update Methods
// ================================================================== 
public void updateFeedBackInfo(String update, boolean append) {
    guiwindow.setFeedback(update, append) ;
}

从优化线程回调 GUI 的示例

//GUI Feedback
this.updateFeedBackInfo("Saving optimization run record to database ... ", 
   APPENDTEXT ) ; // APPENDTEXT = boolean TRUE instructing GUI textbox to append
4

2 回答 2

1

解决方案附录:

在此应用程序的最终测试期间,我更仔细地确定了 GUI 速度变慢的明显原因。通过 GUI 减速,我的意思是复制 2500 个文件之间的区别。减速问题需要将近 20 分钟才能完成复制。应用修复后,复制完全相同的文件只需不到 1 分钟。

问题 副本是通过工作线程处理的。工作线程定期更新 GUI。更新包括 ProgressBar 更新和文本框更新。

文本框更新似乎是问题的根源。我想要的是一个文本框,用于预置状态更新信息——例如“复制文件 C:/hello.txt”——而不是附加(在 SWT 中可用)。要创建我使用的人造前缀(在单独的线程中):

textfeedback.setText(workerthreadinfo + "\n" + textfeedback.getText()) ;

这段小代码似乎是导致速度变慢的罪魁祸首——而且可能很容易看出原因。在每个文件副本中,都会复制整个文本框内容,然后将新信息附加到文本框中。在复制了大约 700 个文件后,这开始陷入困境(您可以明显地看到减速)并在之后继续恶化。

尽管我对此不满意,但解决方法是改用 SWT TextBox append() 方法。

于 2012-08-02T19:54:51.993 回答
1

这听起来不像是线程问题。

如果您在 GUI 线程中意外运行,则在单击按钮后 GUI 将立即死机。所以我认为我们可以排除这种可能性。

您所描述的听起来更像是内存负载/性能问题。我强烈建议将 Visualvm 与您的应用程序连接起来,并特别注意不断增加的内存消耗。此外,使用 visualvm 中包含的分析器可能会暗示消耗大量 cpu 或内存的东西。

于 2012-05-28T17:51:12.377 回答