1

A Pattern that I've seen a few times now and still am unsure if it's correct: I need to invoke some code on the SWT UI thread via Display.syncExec. The code that runs in the UI thread catches a checked exception and wants to propagate this exception to the waiting thread. The pattern looks like this:

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){
 //..
}

Even if there's no real concurrency here, I still think that this is not really safe in terms of visibility: It could well happen that the UI thread stores an exception, but the invoking thread won't see this and still read 'null' when accessing the array after taking control again. Am I right? Is the best way then just to catch SWTException and check its throwable field via instanceof? EDIT: Hm, that won't work so easy if it's a checked exception. I'd need to throw the SWTException from the catch block myself. Better solutions?

Thanks for your help and comments.

4

2 回答 2

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;
    }
  }
于 2012-08-14T12:01:14.263 回答
0

这里有真正的并发,因为 UI Thread 与你的主线程是不同的线程。这肯定会导致 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
于 2012-08-14T11:46:01.223 回答