2012-08-14 36 views
1

一個我現在已經看過幾次的模式,但仍然不確定它是否正確:我需要通過Display.syncExec在SWT UI線程上調用一些代碼。在UI線程中運行的代碼捕獲一個檢查的異常,並希望將此異常傳播到等待的線程。該模式是這樣的:在Display.syncExec過程中捕獲傳播異常以調用線程

SomeCheckedException[] exc = new SomeCheckedException[] { null }; 
display.syncExec(new Runnable(){ 
    public void run(){ 
     try { 
     new Work().something(); 
     } catch (SomeCheckedException e){ 
     exc[0] = e; 
     } 
    } 
}); 

if (exc[0] != null){ 
//.. 
} 

即使這裏沒有真正的併發性,我仍然認爲這是不是在可視性方面真正安全:它很可能發生在UI線程店例外,但調用線程不會看到這個,並且在再次進行控制後訪問數組時仍然讀取'null'。我對嗎?那麼最好的方法就是通過instanceof來抓SWTException並檢查它的可丟棄區域?編輯:嗯,如果它是一個檢查的異常,它不會那麼容易。我需要從自己的catch塊中拋出SWTException。更好的方案?

感謝您的幫助和評論。

回答

1

這是那種情況下AtomicReference的是爲製備:

void foo() throws SomeCheckedException { 
    final AtomicReference<SomeCheckedException> exRef = new AtomicReference<>(); 
    display.syncExec(new Runnable() { 
     public void run() { 
     try { 
      new Work().something(); 
     } catch (SomeCheckedException e) { 
      exRef.set(e); 
     } 
     } 
    }); 
    SomeCheckedException ex = exRef.get(); 
    if (ex != null) { 
     throw ex; 
    } 
    } 
0

這裏有真正的併發,因爲UI線程與主線程不同。這肯定會導致exc [0]爲空。

如果您希望主線程等待UI線程填充將異常放在那裏,那麼您必須同步對該數組的訪問。而且你也需要時間。可能你的主線程必須一遍又一遍地檢查直到它被填滿。或者你可以暫停它(睡眠),並讓UI線程喚醒(通知)。

編輯:一個等待線程的解決方案,沒有通知,只是睡幾毫秒,然後檢查。

//object properties 
volatile Exception e = null; 
volatile Exception completed = false; 
... 
display.syncExec(new Runnable(){ 
    public void run(){ 
     try 
     { 
      ... 
      e = thrownException; 
      .... 
     } catch (...){}; 
     //must be after the try block: 
     completed = true; 
    } 
... 
while(! completed) 
    Thread.sleep(500) //or something, lookup the javadoc 
//after the while ends, you can safely access e 
+0

供參考:[syncExec](http://help.eclipse.org/helios/topic/org.eclipse.platform。 doc.isv/reference/api/org/eclipse/swt/widgets/Display.html#syncExec%28java.lang.Runnable%29),直到在UI線程上執行任務爲止;不需要while循環。 – McDowell 2012-08-14 12:04:48

+0

另外,主動等待並不是一個好的解決方案。 – 2015-03-03 08:56:51