JavaFX 1.2 Async

In JavaFX 1.2, asynchronous operation support was improved. Let's take a brief look at the old approach before diving into the new approach. Here are some URLs that discussed old behavior of asynchronous operation since JavaFX 1.0.

As a summary of old behavior, there was a built-in support for the remote text document to download in a non EDT thread. But this was just one of asynchronous usecases and couldn't be used for many other usecases. In the above blog, James showed how-to get around for the non remote text download case. But the workaround is still cumbersome and forced users to use some implementation classes at com.sun.javafx.runtime.async package.

New javafx.async in JavaFX 1.2

 Now JavaFX 1.2 javafx.async package comes with much clean design to support various asynchronous usecases. Please note that only supported usecase RemoteTextDocument class was removed in 1.2. It's still simple enough to have only 3 new classes namely 2 FX abstract classes(JavaTaskBase/Task) and 1 Java interface(RunnableFuture).

In most of cases, users are required to create their own 2 classes.

  • A Java class(e.g. MyRunnable) that implements RunnableFuture interface. Simply complete the run() method that will be executed in a non-EDT thread by the JavaFX Asynchronous Framework. At this point of time, FX class that extends this interface is not accepted and may result in an exception thrown.
  • A FX class(e.g. MyTask) that extends JavaTaskBase. Simply override the create() method and create/return the RunnableFuture implemented class in the above step. 
Once you create MyTask you can call its start() and stop() functions to control the background work. There are 2 callback function variables(onStart/onDone) and various read-only status variables(started/stopped/failed/causeOfFailure/succeeded/done) that will be set from the non-EDT thread in a different point of time as it progresses.

Here is the UML sequence diagram to illustrate what's happening inside.


What about "progress" from the background thread?  

You will notice JavaTaskBase has the progress related variables such as maxProgress, progress and percentDone. How those are used when I want to be notified the progress? Well the current API doc didn't mention much about it. So hope this will be useful at the moment. Here is my take.

 Let's create a sample that can illustrate new JavaFX Asynchronous Framework with progress. This sample has 2 buttons(start/stop) and the count label at the bottom. The actual counting will happen in a non-EDT java thread simulating a background work. The start button will initiate the counting and the cancel button will stop the counting from the background thread. If the cancel button is not pressed, the counting will be done at 100. And the counted data will be shown in he FX UI as shown here.

async-figure3

 It's your Task responsibility to manipulate setting the maxProgress at the beginning and updating the progress variables as it goes in the run() method. One interesting point is that the maxProgress can be easily set from the FX MyTask probably either in create() or start() function. However the FX variable, progress should be set from the Java MyRunnable class. How can we do that when FX object can't be directly assessed in a Java object?

 The trick is to create a Java interface called Progressable. Let MyTask implement Progressable interface as well.  Pass itself to the java MyRunnable as a Progressable, which is a java interface. The  Progressable interface has only one method, setProgress(val). MyRunnable java class should now be able to call Progressable.setProgress(val) as it goes.

Here is the Progressable interface:


public interface Progressable {
    void setProgress(long progress);
}

 Unfortunately this interface is not a part of javafx.async package. Please copy and paste it to your project source dir. Please note that MyTask is now implementing both JavaTaskBase and Progressable. The percentDone is automatically calculated when the progress is updated. 

 Here is the MyRunnable java class:

import javafx.async.RunnableFuture;
import com.sun.javafx.functions.Function0;

public class MyRunnable implements RunnableFuture {
    CountData counter;
    Progressable task;

    public MyRunnable(CountData cdata, Progressable pi) {
        counter = cdata;
        task = pi;
    }

    @Override
    public void run() throws Exception {
        while(counter.count < 100) {
            counter.count++;
            setProgress(counter.count);
            Thread.sleep(100);
        }
    }

    void setProgress(final long progress) {
        javafx.lang.FX.deferAction(new Function0<Void>() {
            @Override
            public Void invoke() {
                task.setProgress(progress);
                return null;
            }
        });
    }
}

 As all events should be dispatched in the EDT, FX.deferAction() has to be used to invoke MyTask.setProgress(progress). When FX.deferAction() is used, the passed function will be invoked from the EDT. 

 Here is the MyTask FX class:

import javafx.async.\*;

public class MyTask extends JavaTaskBase, Progressable {
    public-init var countData: CountData;
    var peer: MyRunnable;

    override function create(): RunnableFuture {
        peer = new MyRunnable(countData, this);
    }

    override function setProgress(pro: Long) {
        progress = pro;
    }

    override public function start():Void {
        maxProgress = 100;
        progress = 0;
        super.start();
    }
}

 Here is another diagram to illustrate what's happening inside.

async-figure2

 Finally the illustrated sample NetBean project can be downloaded from here (JavaAsyncSample).

There are a couple of things worthwhile to mention at last. 

  1. Tasks are expected to be executed one time (one call to start()  per instance of a Task).
  2. JavaFX code should not be run from objects that support RunnableFuture interface. Some related discussion if you are interested in.

Have a fun with a threading in JavaFX 1.2.



Comments:

[Trackback] まったく人気のないJavaFXネタですが、当面は続くと思われます。使ってみると思った以上に面白いです。 今回は非同期処理の概要としては最終回。非同期処理の進捗を表示するような場合にどうするかです。これまでの非同期処理は終わった時に関数が呼び出されるため、長い処

Posted by やさしいデスマーチ on August 03, 2009 at 12:30 AM PDT #

Thanks for this post, but I don't know how to implement this in my upload applet. I want to update a ProgressBar in FX while java handles the upload. The problem is, that there are several Java classes involved in this process and the actual progress is calculated in a class called by the java class handling the data upload and not by fx directly. Any hint?
Cheers

Posted by guest on August 09, 2009 at 07:17 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on August 20, 2009 at 08:25 PM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on August 26, 2009 at 06:16 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on August 26, 2009 at 06:17 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on August 29, 2009 at 10:51 PM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on August 29, 2009 at 11:00 PM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on September 09, 2009 at 07:09 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on September 09, 2009 at 07:15 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on September 09, 2009 at 07:25 AM PDT #

[Trackback] A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far&#8230; Learning Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Langua...

Posted by Martin Matula&#039;s Blog on September 09, 2009 at 08:07 AM PDT #

Hi good post. Very useful. I have implemented background processing in our Javafx app. It works well.

Now on proper housekeeping, how do we check and make sure the background thread is properly shut down, not hogging memory etc? Our app is memory intensive so I'm trying to clean up after every computation...

thanks
Nick

Posted by Nick Lim on September 17, 2009 at 09:40 AM PDT #

Thanks for this - very interesting.

I wondered what the difference was between invoking javafx.lang.FX.deferAction() and com.sun.javafx.runtime.Entry.deferAction() apart from the obvious signature differences. The latter seems preferable since it doesn't require creating a Function0 instance (maybe it does this internally?).

Posted by Rhys Parsons on November 17, 2009 at 12:48 AM PST #

Hi I was wondering if it is possible to pass data from the main javafx code to the thread. Specifically I'm using the java sound api and want to write to a sourcedataline in the thread using data that's stored in my javafx code.

Thanks,
Ron

Posted by Ron Deang on February 15, 2010 at 07:04 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Hello,
I am Baechul and live in Santa Clara, U.S.A. This is my blog that will talk about Java and JavaFX technologies.

Search

Top Tags
Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today