invokeAndWait for JavaFX

Swing offers the two methods SwingUtilities.invokeAndWait(…) and SwingUtilities.invokeLater(…) to execute a Runnable object on Swings event dispatching thread. You can read more about this methods here.

As I currently know JavaFX provides only Platform.runLater(…) that is the equivalent of SwingUtilities.invokeLater(…). A “runAndWait” method doesn’t exist at the moment. While developing some DataFX stuff and my first Raspberry Pi demo I needed this feature in JavaFX. So I created a runAndWait method that will hopefully be part of DataFX in some future. Until then you can use this code in your project:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javafx.application.Platform;

/**
 * General JavaFX utilities
 * 
 * @author hendrikebbers
 * 
 */
public class FXUtilities {

	/**
	 * Simple helper class.
	 * 
	 * @author hendrikebbers
	 * 
	 */
	private static class ThrowableWrapper {
		Throwable t;
	}

	/**
	 * Invokes a Runnable in JFX Thread and waits while it's finished. Like
	 * SwingUtilities.invokeAndWait does for EDT.
	 * 
	 * @param run
	 *            The Runnable that has to be called on JFX thread.
	 * @throws InterruptedException
	 *             f the execution is interrupted.
	 * @throws ExecutionException
	 *             If a exception is occurred in the run method of the Runnable
	 */
	public static void runAndWait(final Runnable run)
			throws InterruptedException, ExecutionException {
		if (Platform.isFxApplicationThread()) {
			try {
				run.run();
			} catch (Exception e) {
				throw new ExecutionException(e);
			}
		} else {
			final Lock lock = new ReentrantLock();
			final Condition condition = lock.newCondition();
			final ThrowableWrapper throwableWrapper = new ThrowableWrapper();
			lock.lock();
			try {
				Platform.runLater(new Runnable() {

					@Override
					public void run() {
						lock.lock();
						try {
							run.run();
						} catch (Throwable e) {
							throwableWrapper.t = e;
						} finally {
							try {
								condition.signal();
							} finally {
								lock.unlock();
							}
						}
					}
				});
				condition.await();
				if (throwableWrapper.t != null) {
					throw new ExecutionException(throwableWrapper.t);
				}
			} finally {
				lock.unlock();
			}
		}
	}
}

It’s working for all my needs. Please give me some feedback if there are any problems or bug.

8 Responses to invokeAndWait for JavaFX

  1. [...] Ebbers has blogged about his BindableTransition class and invokeAndWait method that he has made available to [...]

  2. Andy sagt:

    Hi Hendrik,
    nice solution! You should be aware of condition.wait() and change it to while(!myCondition) condition.wait() otherwise a condition.signalAll() from user code can create strange behavior. I also add some while(!myCondition && Application.isActive()) condition.await() to my code because it can happen the a Platform.exit() will destroy the JavaFX application thread and the calling thread will wait for ever.
    Otherwise… nice work

    Thank you

    Andy

  3. Tom Brus sagt:

    This will also do the trick (for Runnable and Callable):


    private void runAndWait(Runnable runnable) throws InterruptedException, ExecutionException {
    FutureTask future = new FutureTask(runnable, null);
    Platform.runLater(future);
    future.get();
    }

    private T runAndWait(Callable callable) throws InterruptedException, ExecutionException {
    FutureTask future = new FutureTask(callable);
    Platform.runLater(future);
    return future.get();
    }

    Cheers,
    Tom

  4. K sagt:

    Any reason why you didn’t use com.sun.javafx.application.PlatformImpl.runAndWait(Runnable)?

    TIa,

    K.

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>