views:

69

answers:

2

I've wrote a simple Javafx application which starts a new thread and it works OK from Netbeans. But I'm getting following warning during compilation:

explicit use of threads is not supported

Does it mean that it might now work in all possible devices like mobile phones or browser?

+1  A: 

JavaFX itself must run on the main JavaFX thread, so starting a Thread directly from JavaFX is not currently supported. However, you can create a Java class that spawns a Thread. So, your JavaFX class calls the Java class that then starts a Thread.

Calling back to JavaFX from a Java thread, you need to be on the main JavaFX thread. An example of how to do this is:

import com.sun.javafx.runtime.Entry;
Entry.deferAction( new Runnable() {
                    @Override
                    public void run() {
                        fxListener.onMessage(copy);
                    }
                } );

You should not manipulate the JavaFX objects directly from Java. If you do it from Java, you need to use the javafx.reflect classes.

JimClarke
Great comment. Thank you very much!
Yury Litvinov
A: 

I have to recommend JFXtras (http://jfxtras.org/) XWorker class. It is essentially a workaround to the problem you mentioned in that it allows you to use JavaFX code in a background thread. It works well for most task, but it is also a bit dangerous in that you can easily create code that is not thread-safe with it.

See: http://jfxtras.googlecode.com/svn/site/javadoc/release-0.6/org.jfxtras.async/org.jfxtras.async.XWorker.html

Basic usage:

 var currentImage:Image;
 var worker = XWorker {
     inBackground: function() {
         return Image {url: currentFile.toURL().toString(), height: imageHeight};
     }
     onDone: function(result) {
         currentImage = result as Image;
     }
 }

Everything done within inBackground is done in a background Swing thread. That thread can return a result, which will be passed to onDone. onDone is executed in the JavaFX Event Dispatch Thread (the main thread that all other JavaFX code runs on), so you can return to normal usage. Think of it as the foreground. For the most part you don't want to access anything inBackground that could also be accessed at the same time in "the foreground". You can make an exception to this rule so long as the objects that you are sharing between threads are thread safe. For the most part JavaFX code can't be thread safe, but you can use Java thread safe objects (for example JPA EntityManager factories) or containers such as a BlockingQueue. The latter could be useful for doing a Producer/Consumer model.

Also, if you have a long running task and you want to periodically send updates to "the foreground", you can use publish/process. Here's an example:

 var worker = XWorker {
     inBackground: function() {
         while (true) {
           // Do something
           publish(someStuff);
         } 
     }
     process: function(someStuff: SomeStuff[]):Void {
       // Do something with some stuff. You are now in
       // "the foreground", so you can freely access 
       // JavaFX objects.
     }
     onDone: function(result) {
         currentImage = result as Image;
     }
 }

This is useful for sending things like log messages from a background thread to be displayed in some kind of UI.

Praeus