views:

153

answers:

3

Hello,

I have an UI implemented with Swing. One component does some work that may take some time, so I use SwingUtilities.invokeLater. However, I was reading some old code and found this in an ActionListener:

if (!SwingUtilities.isEventDispatchThread()) {
    SwingUtilities.invokeLater(new Runnable() {
         public void run() {
             // code X
         }
    });
} else {
   // code X
}

I thought that it made sense since it separates code X from the EDT. However, I found it error-prone since I have used it a couple of times and both times I forgot the else part.

The question is: is the SwingUtilities.isEventDispatchThread() checking necessary? Or could I assume that I am not in the EDT and always use invokeLater?

Thanks a lot.

+1  A: 

I believe for your particular use case, checking isEventDispatchThread() is unnecessary. Directly calling invokeLater() will not create a new thread, so this occurs no performance penalty.

JRL
Thank you. In which case it is necessary?
YuppieNetworking
@YuppieNetworking: well, one case where it may be necessary is when you do **not** want to run something on the EDT (like a very lenghty computation)
Webinator
+2  A: 

Invoking later is fine even if you are on the EDT, however it certainly changes the timing of events, so you have to be sure that you were not dependent on the sequence of the code here when you were on the EDT. That being said, a simple way to avoid forgetting the else is to wrap the call in a utility method:

public static void invokeInDispatchThreadIfNeeded(Runnable runnable) {
    if (EventQueue.isDispatchThread()) {
        runnable.run();
    } else {
        SwingUtilities.invokeLater(runnable);
    }
}

That way you never forget the else.

Also, in general in your idom repeating code x is a very bad idea, as you may find later that you have to fix or improve that code and you will only do it in one place, leaving a bug in the other.

Yishai
I agree... it's not DRY at all to do that.
YuppieNetworking
Wait a tick... shouldn't it be `if (!EventQueue.isDispatchThread())` ?
YuppieNetworking
@YuppieNetworking, if you are on the EDT, then you can call the Runnable.run() method directly. If you are not, then you need to call invokelater.
Yishai
A: 

The code really ought to know if it is on the EDT or not (if that is relevant). So java.awt.EventQueue.isDispatchThread should be left to assertions.

Tom Hawtin - tackline