2015-09-07 26 views
0

抛出处理由SwingWorker类的doInBackground方法抛出的异常的正确方法例外正确的方法是从done方法中调用get方法,如所解释herehere来处理由SwingWorker.doInBackground

以下的get方法状态的文档:

如有必要,等待计算完成,然后检索 其结果。

注:在事件指派线程调用​​get所有 事件,包括重新绘制,被处理,直到这 SwingWorker完成。

因此,如果get方法使done方法中的等待,实际上它会阻止在事件指派线程,由于done方法在EDT执行。

但是,执行所提出的方案的一个简单的测试之后,你可能会注意到该EDT没有被阻塞:出现这种现象的原因在于get方法在done方法中调用,所以get在操作的结果后调用被计算出来,因此呼吁它不会阻止美国东部时间。这种动机是否正确?

回答

3

因此,如果get方法导致在done方法内等待,事实上它会阻塞Event Dispatch Thread,因为done方法在EDT上执行。

实际上,如果做被调用时,doInBackground已经返回,因此调用getdone不会阻止事件调度线程。

也是一样,如果你使用的是PropertyChangeListener支持和监控状态DONE

更新

这样的变化,在看看SwingWorker calls 'done' before the 'doInBackground' is finished后,这将意味着调用一个get取消的工作人员会不定期地阻止EDT,基本的工作实际上是通过检查SwingWorker#isCancelled状态来忽略返回结果。让我们面对它,如果工人被取消,返回结果是未知/未定义的,所以最好不要尝试和get它。

作为一个例子(基于从错误的代码)

import java.util.concurrent.ExecutionException; 
import javax.swing.SwingWorker; 

public class Main { 

    public static void main(String[] args) throws InterruptedException { 
     SwingWorker<String, String> worker = new SwingWorker<String, String>() { 
      @Override 
      protected String doInBackground() throws Exception { 
       try { 
        while (!Thread.currentThread().isInterrupted()) { 
         System.out.println("Working..."); 
         Thread.sleep(1000); 

        } 
       } catch (InterruptedException ex) { 
        System.out.println("Got interrupted!"); 
       } 

       try { 
        System.out.println("Cleaning up"); 
        Thread.sleep(10000); 
        System.out.println("Done cleaning"); 
       } catch (InterruptedException ex) { 
        System.out.println("Got interrupted second time!"); 
       } 

       return null; 
      } 

      @Override 
      protected void done() { 
       System.out.println("Done"); 
       if (!isCancelled()) { 
        long start = System.currentTimeMillis(); 
        try { 
         get(); 
        } catch (InterruptedException | ExecutionException ex) { 
         ex.printStackTrace(); 
        } 
        long end = System.currentTimeMillis(); 
        System.out.println("Took " + ((end - start)/1000d)); 
       } else { 
        System.out.println("Was cancelled"); 
       } 
      } 
     }; 

     worker.execute(); 

     Thread.sleep(10000); 

     worker.cancel(true); 
     Thread.sleep(20000); 
    } 
} 
+1

检查一个相关的问题[这里](http://stackoverflow.com/q/7053865/230513)。 – trashgod

+0

如果使用'cancel',这可能不成立。 (bug)https://bugs.openjdk.java.net/browse/JDK-8081474 – Radiodef

+0

@radiodef理论上,如果取消,得到“应该”抛出一个InterruptedException。我有兴趣了解ifnthis只是java 8中的一个bug,或者不是 – MadProgrammer

0
@Override 
protected void done() 
{ 
    try 
    { 
     if(!super.isCancelled()) 
     { 
      super.get(); 
     } 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
    } 
}