2015-05-18 29 views
0

我正在编写一个java swt应用程序来处理服务器日志文件并使用一些分析生成Excel表格,我没有这样做的问题。从线程更新进度条时,SWT窗口变得无响应

当我尝试更新进度栏时出现问题。

以下是代码的基本流程。用户使用directoryDialog选择日志文件并按下开始按钮。点击按钮时,执行以下代码。

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变得无法响应。我无法移动窗户。我无法点击关闭按钮。

我尝试使用摆动工人和display.asyncExec()

+0

日志文件的范围从几MB上绿带。因此,如果UI变得无响应,用户可能会认为应用程序冻结并终止它 – kamesh

+0

我认为读取/处理日志文件是在不同于运行GUI的主线程的线程中完成的? – Stugal

+0

似乎[that](http://stackoverflow.com/a/16714819/2894369)可以帮助你。您也可以尝试使用['Executors'](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html)执行任务,使用'asyncExec()'更新UI。 – alex2410

回答

2

的SWT文件明确指出,ProgressBar.setSelection() 将抛出一个异常(ERROR_THREAD_INVALID_ACCESS)时,不从UI线程调用。这意味着你要么在你的代码的某处吞下异常,要么在UI线程中运行上面的代码。

有一个snippet which shows how to update a ProgressBar from a thread

display.asyncExec(new Runnable() { 
        @Override 
        public void run() { 
         if (bar.isDisposed()) 
          return; 
         bar.setSelection(getProgress); 
        } 
       }); 
+0

对不起,我粘贴错误的代码片段。请在原文中找到更新的代码。我只使用display.asyncExec – kamesh

+0

正如我所说:您正在运行'pm.startProcessing();'在UI线程内部。不要这样做。之前的代码看起来好多了;你只需要用我的答案中的代码替换'progressBar.setSelection(getProgress());'。注意:Swing工人不能在SWT中工作:-) –

+0

感谢Aaron ......它的工作原理...... :)我一直在努力从一周 – kamesh