HEADS-UP: Threading restriction for Animation play, pause, stop now enforced USE CASE

Kevin Rushforth kevin.rushforth at oracle.com
Wed Jan 24 13:15:31 UTC 2024


Thank you to Jurgen for raising the question and to Nir, John, and 
Michael for evaluating it.

I conclude that there is insufficient motivation to revert the change in 
behavior implemented by JDK-8159048 to allow calling the play/pause/stop 
methods of Animation on a background thread. Doing so without making it 
fully multi-thread-safe would be asking for problems, and making it 
fully multi-thread-safe would be a fair bit of work to do it right 
without a clear benefit.

We will proceed with the current approach and let JDK-8159048 stand. 
Further, we will proceed with 
https://bugs.openjdk.org/browse/JDK-8324219 which is under review in 
https://github.com/openjdk/jfx/pull/1342

-- Kevin

On 1/24/2024 12:30 AM, Nir Lisker wrote:
> After playing around with the code sample, I think that this is not 
> the right way to use the animation. The reason is that there is no 
> point in starting the animation before the control is attached to the 
> scenegraph, or even made visible. A small refactoring where, e.g., the 
> controller class exposes a method to start the animation in 
> onSucceeded or just calls it on the FX thread is enough. I never start 
> an animation as part of the construction because it's not the right 
> time. John suggested tying the lifecycle of the animation to the 
> showing of the node, which also solves the problem.
>
> There are animations like PauseTransition or other non-interfering 
> Timelines that could reasonably be run on a background thread. Or 
> maybe just on an unconnected control. This could be a reason to not 
> limit animation methods to the FX thread at the expense of possible 
> user errors, but document the pitfall.
>
> I don't see a good use case for modifying controls in a background 
> thread while still interacting with the scenegraph, hence for adding 
> multithread support.
>
> - Nir
>
> On Mon, Jan 22, 2024, 12:59 Jurgen Doll <javafx at ivoryemr.co.za> wrote:
>
>     Here's an example as requested by Nir:
>
>     publicclassFxTimeLineTest extendsApplication
>
>     {
>
>     privateBorderPane bp= newBorderPane( newLabel("Loading") );
>
>     publicstaticvoidmain( String[] args) {
>
>     launch( FxTimeLineTest.class, args);
>
>     }
>
>     @Override
>
>     publicvoidstart( Stage primaryStage) throwsException {
>
>     newThread( newLoadScene() ).start();
>
>     primaryStage.setScene( newScene( bp, 300, 200 ) );
>
>     primaryStage.setTitle( "Memory Usage");
>
>     primaryStage.show();
>
>     }
>
>     privateclassLoadScene extendsTask<Parent> {
>
>     @OverrideprotectedParent call() throwsException {
>
>     Parent p= FXMLLoader.load( getClass().getResource("TestView.fxml") );
>
>     Thread.sleep( 1000 );
>
>     returnp;
>
>     }
>
>     @Overrideprotectedvoidsucceeded() {
>
>     bp.setCenter( getValue() );
>
>     }
>
>     @Overrideprotectedvoidfailed() {
>
>     getException().printStackTrace();
>
>     }
>
>     }
>
>     }
>
>     ------------------------------------------------------------------------------------------------------
>
>
>     publicclassTestView
>
>     {
>
>     @FXMLprivateLabel memory;
>
>     privatestaticfinaldoubleMEGABYTE= 1024 * 1024;
>
>     @FXMLprivatevoidinitialize()
>
>     {
>
>     varupdater= newTimeline
>
>     (
>
>     newKeyFrame( Duration.seconds(2.5), event->
>
>     {
>
>     varruntime= Runtime.getRuntime();
>
>     doublemaxMemory= runtime.maxMemory() / MEGABYTE;
>
>     doubleusedMemory= (runtime.totalMemory() - runtime.freeMemory()) /
>     MEGABYTE;
>
>     memory.setText( (int) usedMemory+ " MB / "+ (int) maxMemory+" MB");
>
>     })
>
>     );
>
>     updater.setCycleCount(Animation.INDEFINITE); // This FXML is being
>     loaded on a background thread
>
>     updater.play();
>
>     }
>
>     }
>
>     ------------------------------------------------------------------------------------------------------
>
>
>     TestView.fxml
>
>     <?xml version="1.0" encoding="UTF-8"?>
>
>     <?import javafx.scene.control.Label?>
>
>     <?import javafx.scene.layout.StackPane?>
>
>     <StackPane xmlns:fx="http://javafx.com/fxml/1"
>     fx:controller="TestView">
>
>     <children>
>
>     <Label fx:id="memory" text="Current / Max MB" >
>
>     <properties hashCode="12345" />
>
>     </Label>
>
>     </children>
>
>     </StackPane>
>
>
>
>
>     On Sat, 20 Jan 2024 17:08:41 +0200, Nir Lisker <nlisker at gmail.com>
>     wrote:
>
>         Hi Jurgen,
>
>         What I'm confused about the most is what it is you are
>         actually trying to do that necessitates the use of animations
>         outside of the FX thread. You said that you need to initialize
>         controls on another thread, and that you are using Task (both
>         of which are fine), but how does playing animations relate?
>         Playing an animation is something that is done explicitly,
>         usually in order to manipulate data. Can you give a real use
>         case, like a minimized version of what you're doing?
>
>         - Nir
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20240124/4f6657ab/attachment-0001.htm>


More information about the openjfx-dev mailing list