我现在已经看过几次但仍然不确定它是否正确的模式:我需要通过Display.syncExec在SWT UI线程上调用一些代码。在UI线程中运行的代码捕获已检查的异常,并希望将此异常传播到等待的线程。模式看起来像这样:
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'。我对吗?最好的方法是捕获SWTException并通过instanceof
检查其throwable字段?编辑:嗯,如果它是一个检查异常,这将不会那么容易。我需要自己从catch块中抛出SWTException。更好的解决方案?
感谢您的帮助和评论。
答案 0 :(得分: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;
}
}
答案 1 :(得分: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