2015-02-24 53 views
1

我正在使用SwingWorker作爲一種方式來將非swing任務/動作與始終在Event Dispatch Thread中運行的Before和After方法一起包裝(換句話說:在之前調用doInBackground中的抽象方法之後再調用我在完成方法後調用)。由於無論在doInBackground中發生什麼,都必須進行同步,因此最近引發了很多麻煩。我注意到,如果我調用run而不是execute,問題就會消失,但是從我所瞭解的run方法與Thread中的方法相同,它只是從它被調用的完全相同的線程開始執行,而不是創建一個新的一個,因此doInBackground在EDT上執行時會在EDT上執行。我的想法是否正確?我如何將doInBackground方法與調用worker的線程進行同步?正在調用SwingWorker運行錯誤以及如何同步doInBackground?

我用下面的代碼,但它似乎是創建一個線程鎖:

private Object LOCK = new Object();  

public final void method() { 

    someObject.before(); 

    SwingWorker<Void, Void> worker1 = new SwingWorker<Void, Void>() { 

     protected Void doInBackground() throws Exception { 

      methodExt(); 
      return null; 
     } 

     protected void done() { 
      someObject.after(); 
      synchronized (LOCK) { 
       LOCK.notifyAll(); 
      } 
     } 
    }; 

    worker1.execute(); 

    synchronized (LOCK) { 
     try { 
      LOCK.wait(); 
     } catch (InterruptedException exception) { 
      exception.printStackTrace(); 
     } 
    } 
} 
+0

好吧,基本上,你已經規避了SwingWorker給你的任何好處,因爲'LOCK.wait'會阻止EDT ...更好的是使用某種[Observer Pattern](http: //www.oodesign.com/observer-pattern.html)告訴你什麼時候完成了......我不知道,可能會喜歡用'PropertyChangeListener' ....? – MadProgrammer 2015-02-24 09:49:30

+0

@MadProgrammer我看不到PropertyChangeListener如何幫助我。我可以調用someObject.before(); methodExt(); someObject.after();但是然後methodExt在EDT上運行,這是一個錯誤,這就是爲什麼我使用SwingWorker,因爲它有一個我可以使用的直接完成的方法。我的意思是我可以創建一個調用methodExt()的新線程,然後在此線程中創建一個新的Runnable,調用someObject.after()並在EDT上調用它,但我認爲SwingWorker是一種更優雅的方式。 – Mac 2015-02-24 10:22:29

+0

但是,你的LOCK阻塞了EDT ......並且從內存中,你可以簡單地調用SwingWorker#get,這將阻塞到doInBackground返回... – MadProgrammer 2015-02-24 10:37:05

回答

2

你不應該在美國東部時間阻止。整點SwingWorker是它允許你觸發一個任務在後臺線程上運行,並安排額外的代碼在後臺作業完成後在EDT上運行。沒有同時阻塞了EDT。所以如果你想在EDT上運行methodA(),那麼在後臺methodB(),然後methodC()在B完成後回到EDT上,答案是從done()的方法調用methodC()的方法SwingWorker

,而不是試圖做

doSomething(); 
method(); // which blocks waiting for the BG task to complete 
doSomethingElse(); 

,你可以修改method()

public final void method(final Runnable callback) { 

    someObject.before(); 

    SwingWorker<Void, Void> worker1 = new SwingWorker<Void, Void>() { 

     protected Void doInBackground() throws Exception { 
      methodExt(); 
      return null; 
     } 

     protected void done() { 
      someObject.after(); 
      if(callback != null) callback.run(); 
     } 
    }; 

    worker1.execute(); 
} 

,然後把它作爲

doSomething(); 
method(new Runnable() { 
    public void run() { 
    doSomethingElse(); 
    } 
}); 

現在馬上method回報,並不會阻止該EDT ,但doSomethingElse仍然在美國東部時間發生後臺任務完成。

相關問題