Discussion:
Bug: Not on FX application thread exception is inconsistent
Ty Young
2018-11-10 05:58:20 UTC
Permalink
Hi,


My JavaFX program updates API objects in the background via a non FX
thread that, when changed by another program, are reflected in my JavaFX
GUI's controls by property binding, specifically TableView, Slider,
TextField, and ComboBox. Problem is, while JavaFX is OK with this for
TableView, Slider, and TextField, it throws a Not on FX application
thread exception *only* for the ComboBox.


The code for the slider looks like this:

    private class ValueListener implements ChangeListener<Integer>
    {
        @Override
        public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
        {
            slider.getSlider().setValue(newValue);
            slider.getTextBox().setText(newValue.toString());
        }
    }


(the slider variable is misleading, it's actually a VBox that contains a
Slider and a TextField. Need to change it but I digress.)


which works fine. However this:


    private class ValueListener implements ChangeListener<E>
    {
        @Override
        public void changed(ObservableValue<? extends E> observable, E
oldValue, E newValue)
        {
            combo.setValue(newValue);
        }
    }


doesn't for the ComboBox.


Is this a bug or is there some legitimate invisible reason as to why the
slider/textfield isn't throwing an error but the combobox one is?
Ty Young
2018-11-12 21:04:51 UTC
Permalink
Post by Ty Young
Hi,
My JavaFX program updates API objects in the background via a non FX
thread that, when changed by another program, are reflected in my
JavaFX GUI's controls by property binding, specifically TableView,
Slider, TextField, and ComboBox. Problem is, while JavaFX is OK with
this for TableView, Slider, and TextField, it throws a Not on FX
application thread exception *only* for the ComboBox.
    private class ValueListener implements ChangeListener<Integer>
    {
        public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
        {
            slider.getSlider().setValue(newValue);
            slider.getTextBox().setText(newValue.toString());
        }
    }
(the slider variable is misleading, it's actually a VBox that contains
a Slider and a TextField. Need to change it but I digress.)
    private class ValueListener implements ChangeListener<E>
    {
        public void changed(ObservableValue<? extends E> observable, E
oldValue, E newValue)
        {
            combo.setValue(newValue);
        }
    }
doesn't for the ComboBox.
Is this a bug or is there some legitimate invisible reason as to why
the slider/textfield isn't throwing an error but the combobox one is?
Anything at all on this? Does JavaFX have bipolar thread disorder or
something?
Tom Schindl
2018-11-12 23:39:45 UTC
Permalink
Hi,

You are supposed to interact with Nodes who are currently shown in the
SG only only the JavaFX Application Thread.

JavaFX although is not checking each and every property (change) as this
would be too resource intensive but at sensitive cases (eg when
interacting with Glass) it does check that you run on the correct thread.

Even though your TableView, ... updates seem to work you can run into
disasterous states - see eg https://bugs.openjdk.java.net/browse/JDK-8198577

Tom
Post by Ty Young
Hi,
My JavaFX program updates API objects in the background via a non FX
thread that, when changed by another program, are reflected in my JavaFX
GUI's controls by property binding, specifically TableView, Slider,
TextField, and ComboBox. Problem is, while JavaFX is OK with this for
TableView, Slider, and TextField, it throws a Not on FX application
thread exception *only* for the ComboBox.
    private class ValueListener implements ChangeListener<Integer>
    {
        public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
        {
            slider.getSlider().setValue(newValue);
            slider.getTextBox().setText(newValue.toString());
        }
    }
(the slider variable is misleading, it's actually a VBox that contains a
Slider and a TextField. Need to change it but I digress.)
    private class ValueListener implements ChangeListener<E>
    {
        public void changed(ObservableValue<? extends E> observable, E
oldValue, E newValue)
        {
            combo.setValue(newValue);
        }
    }
doesn't for the ComboBox.
Is this a bug or is there some legitimate invisible reason as to why the
slider/textfield isn't throwing an error but the combobox one is?
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Ty Young
2018-11-13 03:00:58 UTC
Permalink
Post by Tom Schindl
Hi,
You are supposed to interact with Nodes who are currently shown in the
SG only only the JavaFX Application Thread.
I never touch the GUI in my other threads, ever. The threads simply
change the value of a type stored in a property. The ChangeListener that
is used is created in the GUI JavaFX thread.
Post by Tom Schindl
JavaFX although is not checking each and every property (change) as this
would be too resource intensive but at sensitive cases (eg when
interacting with Glass) it does check that you run on the correct thread.
The update process for updating my API objects is slow(for reasons
beyond my control), so even assuming I somehow manage to magically
update everything in the GUI thread, how the hell do you fix the GUI
stuttering at that point?


Really, having an entire application do all of it's processing on one
thread in 2018 is really just idiotic and asking for trouble.
Post by Tom Schindl
Even though your TableView, ... updates seem to work you can run into
disasterous states - see eg https://bugs.openjdk.java.net/browse/JDK-8198577
Tom
I'm not sure what the bug is about since the description really doesn't
give much info however I really haven't noticed anything, even long term
with it being open for 8+ hours. These objects are update very
frequently as well.


To be clear, this isn't some business application that gets info from a
database or something.
Post by Tom Schindl
Post by Ty Young
Hi,
My JavaFX program updates API objects in the background via a non FX
thread that, when changed by another program, are reflected in my JavaFX
GUI's controls by property binding, specifically TableView, Slider,
TextField, and ComboBox. Problem is, while JavaFX is OK with this for
TableView, Slider, and TextField, it throws a Not on FX application
thread exception *only* for the ComboBox.
    private class ValueListener implements ChangeListener<Integer>
    {
        public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
        {
            slider.getSlider().setValue(newValue);
            slider.getTextBox().setText(newValue.toString());
        }
    }
(the slider variable is misleading, it's actually a VBox that contains a
Slider and a TextField. Need to change it but I digress.)
    private class ValueListener implements ChangeListener<E>
    {
        public void changed(ObservableValue<? extends E> observable, E
oldValue, E newValue)
        {
            combo.setValue(newValue);
        }
    }
doesn't for the ComboBox.
Is this a bug or is there some legitimate invisible reason as to why the
slider/textfield isn't throwing an error but the combobox one is?
Brian Hudson
2018-11-13 03:12:00 UTC
Permalink
JavaFX like every other modern UI framework is single threaded.

The updating of your “API objects” can and should remain on a background
thread, however once updated the changes which trigger an update to your UI
(changing a value in a bound property) should occur on the JavaFX thread
via Platform.runLater for example.

Also, take the attitude down a notch or two.

Brian
Post by Ty Young
Post by Tom Schindl
Hi,
You are supposed to interact with Nodes who are currently shown in the
SG only only the JavaFX Application Thread.
I never touch the GUI in my other threads, ever. The threads simply
change the value of a type stored in a property. The ChangeListener that
is used is created in the GUI JavaFX thread.
Post by Tom Schindl
JavaFX although is not checking each and every property (change) as this
would be too resource intensive but at sensitive cases (eg when
interacting with Glass) it does check that you run on the correct thread.
The update process for updating my API objects is slow(for reasons
beyond my control), so even assuming I somehow manage to magically
update everything in the GUI thread, how the hell do you fix the GUI
stuttering at that point?
Really, having an entire application do all of it's processing on one
thread in 2018 is really just idiotic and asking for trouble.
Post by Tom Schindl
Even though your TableView, ... updates seem to work you can run into
disasterous states - see eg
https://bugs.openjdk.java.net/browse/JDK-8198577
Post by Tom Schindl
Tom
I'm not sure what the bug is about since the description really doesn't
give much info however I really haven't noticed anything, even long term
with it being open for 8+ hours. These objects are update very
frequently as well.
To be clear, this isn't some business application that gets info from a
database or something.
Post by Tom Schindl
Post by Ty Young
Hi,
My JavaFX program updates API objects in the background via a non FX
thread that, when changed by another program, are reflected in my JavaFX
GUI's controls by property binding, specifically TableView, Slider,
TextField, and ComboBox. Problem is, while JavaFX is OK with this for
TableView, Slider, and TextField, it throws a Not on FX application
thread exception *only* for the ComboBox.
private class ValueListener implements ChangeListener<Integer>
{
@Override
public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
{
slider.getSlider().setValue(newValue);
slider.getTextBox().setText(newValue.toString());
}
}
(the slider variable is misleading, it's actually a VBox that contains a
Slider and a TextField. Need to change it but I digress.)
private class ValueListener implements ChangeListener<E>
{
@Override
public void changed(ObservableValue<? extends E> observable, E
oldValue, E newValue)
{
combo.setValue(newValue);
}
}
doesn't for the ComboBox.
Is this a bug or is there some legitimate invisible reason as to why the
slider/textfield isn't throwing an error but the combobox one is?
Ty Young
2018-11-13 04:38:08 UTC
Permalink
Post by Brian Hudson
JavaFX like every other modern UI framework is single threaded.
Which in itself is fine, running *just* the UI isn't much on modern
processors. Adding a bunch of API object updates that cause thread
slowdown to the mix that can cause UI stuttering is, again, asking for
trouble.


And how is TableView, Slider, TextField, etc all working just fine but
ComboBox freaks out? What's so special about ComboBox? Is there some
hack I can do to not trigger the exception?
Post by Brian Hudson
The updating of your “API objects” can and should remain on a
background thread, however once updated the changes which trigger an
update to your UI (changing a value in a bound property) should occur
on the JavaFX thread via Platform.runLater for example.
Doing all this is just messy, inefficient, and duplicating code. It
would involve creating Runnable implementations that does about 10 lines
of code with objects that get updated as fast as they can be with
different object types, resulting in more threads and garbage being
created. Using generic magic isn't really a solution either because
different API objects convert data from String to some other type
depending on the implementation.


Would it not be possible to have a runPlatformListener method that just
runs the ChangeListener on the platform thread automatically? It would
reduce the amount of garbage dramatically since JavaFX only ever fires a
change event if the object is itself different(in other words, if the
current value is 0 and the new value is 0, there is no change) which is
nice and efficient.
Post by Brian Hudson
Also, take the attitude down a notch or two.
Brian
Post by Tom Schindl
Hi,
You are supposed to interact with Nodes who are currently shown
in the
Post by Tom Schindl
SG only only the JavaFX Application Thread.
I never touch the GUI in my other threads, ever. The threads simply
change the value of a type stored in a property. The
ChangeListener that
is used is created in the GUI JavaFX thread.
Post by Tom Schindl
JavaFX although is not checking each and every property (change)
as this
Post by Tom Schindl
would be too resource intensive but at sensitive cases (eg when
interacting with Glass) it does check that you run on the
correct thread.
The update process for updating my API objects is slow(for reasons
beyond my control), so even assuming I somehow manage to magically
update everything in the GUI thread, how the hell do you fix the GUI
stuttering at that point?
Really, having an entire application do all of it's processing on one
thread in 2018 is really just idiotic and asking for trouble.
Post by Tom Schindl
Even though your TableView, ... updates seem to work you can run
into
Post by Tom Schindl
disasterous states - see eg
https://bugs.openjdk.java.net/browse/JDK-8198577
Post by Tom Schindl
Tom
I'm not sure what the bug is about since the description really doesn't
give much info however I really haven't noticed anything, even long term
with it being open for 8+ hours. These objects are update very
frequently as well.
To be clear, this isn't some business application that gets info from a
database or something.
Post by Tom Schindl
Post by Ty Young
Hi,
My JavaFX program updates API objects in the background via a
non FX
Post by Tom Schindl
Post by Ty Young
thread that, when changed by another program, are reflected in
my JavaFX
Post by Tom Schindl
Post by Ty Young
GUI's controls by property binding, specifically TableView, Slider,
TextField, and ComboBox. Problem is, while JavaFX is OK with
this for
Post by Tom Schindl
Post by Ty Young
TableView, Slider, and TextField, it throws a Not on FX application
thread exception *only* for the ComboBox.
      private class ValueListener implements ChangeListener<Integer>
      {
          public void changed(ObservableValue<? extends Integer>
observable, Integer oldValue, Integer newValue)
          {
              slider.getSlider().setValue(newValue);
slider.getTextBox().setText(newValue.toString());
          }
      }
(the slider variable is misleading, it's actually a VBox that
contains a
Post by Tom Schindl
Post by Ty Young
Slider and a TextField. Need to change it but I digress.)
      private class ValueListener implements ChangeListener<E>
      {
          public void changed(ObservableValue<? extends E>
observable, E
Post by Tom Schindl
Post by Ty Young
oldValue, E newValue)
          {
              combo.setValue(newValue);
          }
      }
doesn't for the ComboBox.
Is this a bug or is there some legitimate invisible reason as
to why the
Post by Tom Schindl
Post by Ty Young
slider/textfield isn't throwing an error but the combobox one is?
Tom Schindl
2018-11-13 06:12:00 UTC
Permalink
I'm sorry that I'm the one to bring you the bad news that you need to do
the work and can't offload multi-threading to JavaFX.

I already explain why it *seems* to work one some elements (until it
breaks like shown in the bug-report I referenced) and for others it
breaks immediately because they somehow call out to native APIs (like
win32, ...) and hence are guarded with checks.

I can simply say it won't work and it won't change (well I'm not the one
in charge of such a decision but I frankly can't believe it will). You
are the one supposed to deal with this like you have to deal with that
in Swing, Qt, WPF, Win32-API, Cocoa-API, Gtk, ... - you need to sync
yourself back to the UI-Thread if you want to access resources.

You are right. If there are many updates from the backend-system you
would queue a lot of Runnables using Platform.runLater() who can get you
in trouble.

There are others ways to sync back to the JavaFX UI-Thread but
Platform.runLater() is the simplest with the least amount of work and
until you run into problems you should stick to that.

This is my last reply in this thread, as there's nothing more to say on
this topic from my side, there are many resources out there discussing
Platform.runLater and friends but that's something you can (and could
have) googled for and anyways looks like you don't want to listen.

Tom
Post by Ty Young
Post by Brian Hudson
JavaFX like every other modern UI framework is single threaded.
Which in itself is fine, running *just* the UI isn't much on modern
processors. Adding a bunch of API object updates that cause thread
slowdown to the mix that can cause UI stuttering is, again, asking for
trouble.
And how is TableView, Slider, TextField, etc all working just fine but
ComboBox freaks out? What's so special about ComboBox? Is there some
hack I can do to not trigger the exception?
Post by Brian Hudson
The updating of your “API objects” can and should remain on a
background thread, however once updated the changes which trigger an
update to your UI (changing a value in a bound property) should occur
on the JavaFX thread via Platform.runLater for example.
Doing all this is just messy, inefficient, and duplicating code. It
would involve creating Runnable implementations that does about 10 lines
of code with objects that get updated as fast as they can be with
different object types, resulting in more threads and garbage being
created. Using generic magic isn't really a solution either because
different API objects convert data from String to some other type
depending on the implementation.
Would it not be possible to have a runPlatformListener method that just
runs the ChangeListener on the platform thread automatically? It would
reduce the amount of garbage dramatically since JavaFX only ever fires a
change event if the object is itself different(in other words, if the
current value is 0 and the new value is 0, there is no change) which is
nice and efficient.
Post by Brian Hudson
Also, take the attitude down a notch or two.
Brian
    > Hi,
    >
    > You are supposed to interact with Nodes who are currently shown
    in the
    > SG only only the JavaFX Application Thread.
    I never touch the GUI in my other threads, ever. The threads simply
    change the value of a type stored in a property. The
    ChangeListener that
    is used is created in the GUI JavaFX thread.
    >
    > JavaFX although is not checking each and every property (change)
    as this
    > would be too resource intensive but at sensitive cases (eg when
    > interacting with Glass) it does check that you run on the
    correct thread.
    The update process for updating my API objects is slow(for reasons
    beyond my control), so even assuming I somehow manage to magically
    update everything in the GUI thread, how the hell do you fix the GUI
    stuttering at that point?
    Really, having an entire application do all of it's processing on one
    thread in 2018 is really just idiotic and asking for trouble.
    >
    > Even though your TableView, ... updates seem to work you can run
    into
    > disasterous states - see eg
    https://bugs.openjdk.java.net/browse/JDK-8198577
    >
    > Tom
    I'm not sure what the bug is about since the description really
    doesn't
    give much info however I really haven't noticed anything, even
    long term
    with it being open for 8+ hours. These objects are update very
    frequently as well.
    To be clear, this isn't some business application that gets info
    from a
    database or something.
    >> Hi,
    >>
    >>
    >> My JavaFX program updates API objects in the background via a
    non FX
    >> thread that, when changed by another program, are reflected in
    my JavaFX
    >> GUI's controls by property binding, specifically TableView,
Slider,
    >> TextField, and ComboBox. Problem is, while JavaFX is OK with
    this for
    >> TableView, Slider, and TextField, it throws a Not on FX
application
    >> thread exception *only* for the ComboBox.
    >>
    >>
    >>
    >>      private class ValueListener implements
ChangeListener<Integer>
    >>      {
    >>          public void changed(ObservableValue<? extends Integer>
    >> observable, Integer oldValue, Integer newValue)
    >>          {
    >>              slider.getSlider().setValue(newValue);
    >> slider.getTextBox().setText(newValue.toString());
    >>          }
    >>      }
    >>
    >>
    >> (the slider variable is misleading, it's actually a VBox that
    contains a
    >> Slider and a TextField. Need to change it but I digress.)
    >>
    >>
    >>
    >>
    >>      private class ValueListener implements ChangeListener<E>
    >>      {
    >>          public void changed(ObservableValue<? extends E>
    observable, E
    >> oldValue, E newValue)
    >>          {
    >>              combo.setValue(newValue);
    >>          }
    >>      }
    >>
    >>
    >> doesn't for the ComboBox.
    >>
    >>
    >> Is this a bug or is there some legitimate invisible reason as
    to why the
    >> slider/textfield isn't throwing an error but the combobox one is?
    >>
    >>
    >>
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Ty Young
2018-11-13 11:05:54 UTC
Permalink
Post by Tom Schindl
I'm sorry that I'm the one to bring you the bad news that you need to do
the work and can't offload multi-threading to JavaFX.
I already explain why it *seems* to work one some elements (until it
breaks like shown in the bug-report I referenced) and for others it
breaks immediately because they somehow call out to native APIs (like
win32, ...) and hence are guarded with checks.
I can simply say it won't work and it won't change (well I'm not the one
in charge of such a decision but I frankly can't believe it will). You
are the one supposed to deal with this like you have to deal with that
in Swing, Qt, WPF, Win32-API, Cocoa-API, Gtk, ... - you need to sync
yourself back to the UI-Thread if you want to access resources.
You are right. If there are many updates from the backend-system you
would queue a lot of Runnables using Platform.runLater() who can get you
in trouble.
There are others ways to sync back to the JavaFX UI-Thread but
Platform.runLater() is the simplest with the least amount of work and
until you run into problems you should stick to that.
Because everything is ran in different places and there is no built-in
way to wait for the runnable to finish, some GUI code that notifies the
user of an API object's change breaks because the object hasn't been
updated yet.
Post by Tom Schindl
This is my last reply in this thread, as there's nothing more to say on
this topic from my side, there are many resources out there discussing
Platform.runLater and friends but that's something you can (and could
have) googled for and anyways looks like you don't want to listen.
All Google turns up is Platform.runLater and Platform.runAndWait.
Platform.runAndWait isn't even publicly usable unless I edit the source
and make it public. I knew using Platform.runLater was going to cause
problems which is why I really didn't want to use it to begin with.


This isn't me not doing my research, this is objectively JavaFX not
providing the functionality that is necessary to do something rather
trivial: update an API object and provide information from that API
object right after it's updated to the user(without ChangeListener).


I understand that there may be very technical reasons for not making it
public, however it is still *majorly* problematic that it doesn't exist.
Not being able to tell when a runnable has finished executing(besides
ChangeListeners) is a big deal.
Post by Tom Schindl
Tom
Post by Ty Young
Post by Brian Hudson
JavaFX like every other modern UI framework is single threaded.
Which in itself is fine, running *just* the UI isn't much on modern
processors. Adding a bunch of API object updates that cause thread
slowdown to the mix that can cause UI stuttering is, again, asking for
trouble.
And how is TableView, Slider, TextField, etc all working just fine but
ComboBox freaks out? What's so special about ComboBox? Is there some
hack I can do to not trigger the exception?
Post by Brian Hudson
The updating of your “API objects” can and should remain on a
background thread, however once updated the changes which trigger an
update to your UI (changing a value in a bound property) should occur
on the JavaFX thread via Platform.runLater for example.
Doing all this is just messy, inefficient, and duplicating code. It
would involve creating Runnable implementations that does about 10 lines
of code with objects that get updated as fast as they can be with
different object types, resulting in more threads and garbage being
created. Using generic magic isn't really a solution either because
different API objects convert data from String to some other type
depending on the implementation.
Would it not be possible to have a runPlatformListener method that just
runs the ChangeListener on the platform thread automatically? It would
reduce the amount of garbage dramatically since JavaFX only ever fires a
change event if the object is itself different(in other words, if the
current value is 0 and the new value is 0, there is no change) which is
nice and efficient.
Post by Brian Hudson
Also, take the attitude down a notch or two.
Brian
    > Hi,
    >
    > You are supposed to interact with Nodes who are currently shown
    in the
    > SG only only the JavaFX Application Thread.
    I never touch the GUI in my other threads, ever. The threads simply
    change the value of a type stored in a property. The
    ChangeListener that
    is used is created in the GUI JavaFX thread.
    >
    > JavaFX although is not checking each and every property (change)
    as this
    > would be too resource intensive but at sensitive cases (eg when
    > interacting with Glass) it does check that you run on the
    correct thread.
    The update process for updating my API objects is slow(for reasons
    beyond my control), so even assuming I somehow manage to magically
    update everything in the GUI thread, how the hell do you fix the GUI
    stuttering at that point?
    Really, having an entire application do all of it's processing on one
    thread in 2018 is really just idiotic and asking for trouble.
    >
    > Even though your TableView, ... updates seem to work you can run
    into
    > disasterous states - see eg
    https://bugs.openjdk.java.net/browse/JDK-8198577
    >
    > Tom
    I'm not sure what the bug is about since the description really
    doesn't
    give much info however I really haven't noticed anything, even
    long term
    with it being open for 8+ hours. These objects are update very
    frequently as well.
    To be clear, this isn't some business application that gets info
    from a
    database or something.
    >> Hi,
    >>
    >>
    >> My JavaFX program updates API objects in the background via a
    non FX
    >> thread that, when changed by another program, are reflected in
    my JavaFX
    >> GUI's controls by property binding, specifically TableView,
Slider,
    >> TextField, and ComboBox. Problem is, while JavaFX is OK with
    this for
    >> TableView, Slider, and TextField, it throws a Not on FX
application
    >> thread exception *only* for the ComboBox.
    >>
    >>
    >>
    >>      private class ValueListener implements
ChangeListener<Integer>
    >>      {
    >>          public void changed(ObservableValue<? extends Integer>
    >> observable, Integer oldValue, Integer newValue)
    >>          {
    >>              slider.getSlider().setValue(newValue);
    >> slider.getTextBox().setText(newValue.toString());
    >>          }
    >>      }
    >>
    >>
    >> (the slider variable is misleading, it's actually a VBox that
    contains a
    >> Slider and a TextField. Need to change it but I digress.)
    >>
    >>
    >>
    >>
    >>      private class ValueListener implements ChangeListener<E>
    >>      {
    >>          public void changed(ObservableValue<? extends E>
    observable, E
    >> oldValue, E newValue)
    >>          {
    >>              combo.setValue(newValue);
    >>          }
    >>      }
    >>
    >>
    >> doesn't for the ComboBox.
    >>
    >>
    >> Is this a bug or is there some legitimate invisible reason as
    to why the
    >> slider/textfield isn't throwing an error but the combobox one is?
    >>
    >>
    >>
Mario Torre
2018-11-13 15:26:11 UTC
Permalink
Il giorno mar 13 nov 2018 alle ore 16:11 Ty Young
Post by Ty Young
Post by Brian Hudson
JavaFX like every other modern UI framework is single threaded.
Which in itself is fine, running *just* the UI isn't much on modern
processors. Adding a bunch of API object updates that cause thread
slowdown to the mix that can cause UI stuttering is, again, asking for
trouble.
I think you're missing the key point of synchronising different
threads for different tasks. You can do all the processing of your
objects in any thread you want, but the moment they need to update UI
state, this needs to be piped into the UI thread.
Post by Ty Young
And how is TableView, Slider, TextField, etc all working just fine but
ComboBox freaks out? What's so special about ComboBox? Is there some
hack I can do to not trigger the exception?
Just luck.

I suggest you to study and learn about concurrent programming and read
some basic tutorials on graphical programming, the issues you are
encountering aren't anything new, most frameworks work the same way.

Cheers,
Mario
--
pgp key: http://subkeys.pgp.net/ PGP Key ID: 80F240CF
Fingerprint: BA39 9666 94EC 8B73 27FA FC7C 4086 63E3 80F2 40CF

Java Champion - Blog: http://neugens.wordpress.com - Twitter: @neugens
Proud GNU Classpath developer: http://www.classpath.org/
OpenJDK: http://openjdk.java.net/projects/caciocavallo/

Please, support open standards:
http://endsoftpatents.org/
Tom Eugelink
2018-11-13 16:06:43 UTC
Permalink
This isn't me not doing my research, this is objectively JavaFX not providing the functionality that is necessary to do something rather trivial: update an API object and provide information from that API object right after it's updated to the user(without ChangeListener).
You are not using the right tool for the job. Thread management is not the responsibility of the UI toolkit, all it does is require that you got your stuff in order and run its code on the appropriate thread. Platform.run and runAndWait are just entry points for doing that, not multithreading solutions. There are good libraries for asynchronous execution; just use CompletableFuture, RxJava or JDeffered. RxJava even has build in support for putting a task back onto the JavaFX UI thread: observeOn(JavaFxScheduler.platform()).
Tom Schindl
2018-11-13 06:17:18 UTC
Permalink
Post by Ty Young
Post by Tom Schindl
Hi,
You are supposed to interact with Nodes who are currently shown in the
SG only only the JavaFX Application Thread.
I never touch the GUI in my other threads, ever. The threads simply
change the value of a type stored in a property. The ChangeListener that
is used is created in the GUI JavaFX thread.
It does not matter on which thread you create a ChangeListener the
important thing is on Thread causes the change-listener to trigger.
*None* of the JavaFX code-structures (Property, ObservableList) are
multi-thread-safe you accessing them from multiple threads at the same
time is asking for trouble.

Tom
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Loading...