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.

[...] Ebbers has blogged about his BindableTransition class and invokeAndWait method that he has made available to [...]
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
Hi Andy,
where can I find your invokeAndWait code?
Hi Hendrik,
you can find it here: http://code.google.com/p/jacp/source/browse/branches/working/JACP.JavaFX/src/main/java/org/jacp/javafx/rcp/worker/AFXComponentWorker.java
Andy
Hi Andy,
I have a question about your implementation:
The condition only “lifes” inside the invokeAndWait method and can’t be accessed from outside. In this case I do not understand how user code can create strange behavior (like calling condition.signal() / signalAll() ). Maybe I miss some point. So can you give me an example? I think the Platform.exit() problem is a good objection. I will study this behavior the next days to add exception handling to my code.
Greetings,
Hendrik
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
Any reason why you didn’t use com.sun.javafx.application.PlatformImpl.runAndWait(Runnable)?
TIa,
K.
Hi,
cause this is a private API and can change any time.