Hi Michael

It seems we are misunderstanding one another.

Firstly I agree that the animation code itself must and always has run only on the FX thread.

So for example in the following code:

   new KeyFrame( Duration.seconds(2.5), event ->
   {
      int maxMemory = ....;
      int usedMemory = ....;
      memoryLabel.setText( usedMemory +" MB / "+ maxMemory +" MB" );
   })

The lambda part ALWAYS executes on the FX thread by default, no matter on which thread this KeyFrame is created.


And we all agree that the following is ILLEGAL:

   new KeyFrame( Duration.seconds(2.5), event ->
   {
new Thread( () -> memoryLabel.setText( usedMemory +" MB / "+ maxMemory +" MB" ) ).start();
   })


With the above clarified, what I'm contending is that the following can be excuted on any thread:

   var updater = new Timeline
   (
      new KeyFrame( Duration.seconds(2.5), event ->
      {
         int maxMemory = ....;
         int usedMemory = ....;
         memoryLabel.setText( usedMemory +" MB / "+ maxMemory +" MB" );
      })
   );
   updater.setCycleCount(Animation.INDEFINITE);
   updater.play();


The reason is because play, stop, and pause simply causes the Timeline to be added too or removed from an array in AbstractPrimaryTimer. If a pulse is busy executing so that the array is currently being accessed by the FX thread then a copy of the array is made and the addition/removal is made to the copy. (However there is a bug in this code that causes an NPE under certain conditions.)

So when the API documentation says that it's asynchronous it means that the 'animation' execution may not yet have started/stopped when the call returns depending on when during the pulse the method was invoked. If play is invoked just before the next pulse then the 'animation' could be running, or if stop is invoked just as a pulse completes then it will not be executing. Otherwise the 'animation' will only actually be (not) executing in the next pulse.

Hope this clarifies things.

Regards
Jurgen

Reply via email to