24

Please explain invokeAndWait() method in SwingUtilities.I am unable to understand this. Explain it very clearly. It would be of great help if you try out with an example.

Edited to add @noob's expansion of the question:

What's not clear about this?

Here's a modified usage example:

import javax.swing.SwingUtilities;

public class InvokeAndWaitStuff 
{
    public static void main(String[] args)
    {
        final Runnable doHelloWorld = new Runnable() {
             public void run() {
                 System.out.println("Hello World on " + Thread.currentThread());
             }
         };

         Thread appThread = new Thread() {
             public void run() {
                 try {
                     SwingUtilities.invokeAndWait(doHelloWorld);
                 }
                 catch (Exception e) {
                     e.printStackTrace();
                 }
                 System.out.println("Finished on " + Thread.currentThread());
             }
         };
         appThread.start();
    }
}

Output:

Hello World on Thread[AWT-EventQueue-0,6,main]
Finished on Thread[Thread-0,5,main]

And why is this important?:

Causes doHelloWorld.run() to be executed synchronously on the AWT event dispatching thread. This call blocks until all pending AWT events have been processed and (then) doHelloWorld.run() returns. This method should be used when an application thread needs to update the GUI.

As far as I can tell, this is basically a bottleneck that forces GUI updates to be executed synchronously by a single thread, rather than asynchronously by multiple threads, which can potentially be unsafe.

javanna
  • 59,145
  • 14
  • 144
  • 125
saplingPro
  • 20,769
  • 53
  • 137
  • 195

2 Answers2

57

To understand what invokeAndWait() does, you first need to understand the event/thread model of Swing.

Basically, everything that affects the GUI in any way must happen on a single thread. This is because experience shows that a multi-threaded GUI is impossible to get right.

In Swing, this special GUI thread is called the Event Dispatch Thread, or EDT. It is started as soon as a Swing top-level component is displayed, and it's bascially a worker thread that has a FIFO queue of event objects that it executes one after another.

When a Swing GUI needs to be drawn or updated, the JRE places an event on the EDT queue. User actions that cause listeners to be called start as events on the EDT queue. And (this is this is the important part) everything your program does that changes the GUI (like registering listeners, adding/removing GUI components or changing model data that the GUI displays) must be placed in the EDT queue, or the GUI can get corrupted.

And now for the finish: invokeAndWait() places the Runnable you pass to it into the EDT event queue and waits until the EDT has executed it. This should be used when a non-GUI thread needs to do something that affects the GUI, but also needs to wait until it is actually done before it can continue. If you just want to do something that affects the GUI but do not care when it is finished, you should instead use invokeLater().

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • @Michael: Is there something similar to `invokeAndWait` for threads other than the EDT? I find that this would be INCREDIBLY useful, especially if you desire sequential execution of multiple tasks... – mre Mar 31 '11 at 13:15
  • 1
    @noob: Executors.newSingleThreadExecutor() from java.util.concurrent produces an ExecutorService that basically works just like the EDT. You can then submit() Runnables and call get() on the returned Future to wait for its completion. – Michael Borgwardt Mar 31 '11 at 13:24
  • @Michael: Thanks! And I guess my answer was wrong, or something since it was deleted. Awesome! – mre Mar 31 '11 at 13:34
  • 1
    @noob: Take a look here, for example, which might give you some ideas. http://stackoverflow.com/questions/1322147/help-with-java-executors-wait-for-task-termination – andersoj Mar 31 '11 at 13:34
  • @noob: It wasn't framed as an answer, but as an extension to your original question. I copied the contents into your question as an edit and a moderator removed your answer. No big deal -- remember that SO is trying not just to answer your question in the here and now, but keep a clean Q+A for future searchers/questioners as well. – andersoj Mar 31 '11 at 13:36
  • @andersoj: Appreciate the explanation, and the link! – mre Mar 31 '11 at 13:38
  • 1
    It's noteworthy that invokeandwait should not be called in the EDT or the program will deadlock... – George Xavier May 13 '19 at 16:52
1

I had a similar problem in a JTable. The program was blocked somewhere in "scrollRectToVisible" method. I have replaced the call by wrapping it in an invokeLater call. The invokeAndWait did not resolve my block problem.

    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            table.scrollRectToVisible(r);
        }

    });