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

Kevin Rushforth kevin.rushforth at oracle.com
Wed Jan 24 14:20:45 UTC 2024


I'd like to hear from the others on this. I don't see any fundamental 
problem with having the play/pause/stop methods wrap their 
implementation in a runLater (if not on the FX Application thread 
already), and documenting that it does so, if we can get general agreement.

-- Kevin


On 1/24/2024 5:29 AM, Jurgen Doll wrote:
> Hi Kevin
>
> If I may make one more final appeal then to an alternative solution 
> please.
>
> Could we then instead of throwing an Exception rather invoke runLater 
> if needed inside play, stop, and resume.
>
> Putting the onus on the developer is fine if it is the developer that 
> is invoking the call, but if it's in a library then it's a no go.
>
> In my application I have two libraries that I know of where this 
> happens. The major problem is that with FX22 as it now stands my 
> application just crashes because play() does an FX thread check and 
> throws an Exception which it never did before. There are bound to be 
> other applications out there that are going to find themselves in a 
> similar position.
>
> PLEASE !
>
> Regards
> Jurgen
>
>
>
> On Wed, 24 Jan 2024 15:15:31 +0200, Kevin Rushforth 
> <kevin.rushforth at oracle.com> wrote:
>
>     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
>>
>>         (
>>
>>         newK eyFrame( 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
>>
>
>
>
>
> -- 
> Using Opera's mail client: http://www.opera.com/mail/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20240124/514e1381/attachment-0001.htm>


More information about the openjfx-dev mailing list