2012-08-14 34 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