B4J Question Strange Error: Not on FX application thread

Midimaster

Active Member
Licensed User
I move my app from B4A to B4J and it is the first time I use B4J.

I have two modules Main and Player.Bas and in my opinion I do nothing with multi-threading. I divided the code in this two modules to get a clear separation between UI-related code and pure data processing.

Therefore I often I call functions, which are in Player, from Main. Sometimes I call functions, which are in Main from Player

Now I have two harmless looking functions which cause an error in Release Mode. (In Debug mode it seems to work)
setze songname=BlueChampagne
main._setzesongtitellabel (java line: 677)
java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-5-thread-1
at javafx.graphics/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:291)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:424)
at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:471)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at javafx.controls/javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:272)
at javafx.controls/javafx.scene.control.skin.LabeledSkinBase.lambda$new$11(LabeledSkinBase.java:220)
at javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$1(LambdaMultiplePropertyChangeListenerHandler.java:49)
at javafx.base/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:86)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
at javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
at javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
at javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
at javafx.base/javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.controls/javafx.scene.control.Labeled.setText(Labeled.java:147)
at anywheresoftware.b4j.objects.LabeledWrapper.setText(LabeledWrapper.java:43)
at b4j.example.main._setzesongtitellabel(main.java:677)
at b4j.example.player._importheader(player.java:835)
at b4j.example.player._erstmalssongladen(player.java:637)
at b4j.example.player$ResumableSub_LoadSong.resume(player.java:1175)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:136)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:85)
at a.a.a.f.a.a(SourceFile:88)
at a.a.a.f.a.c(SourceFile:155)
at a.a.a.f.a.a(SourceFile:163)
at a.a.a.g.a$3.run(SourceFile:156)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
NEU=BlueChampagne

The calling function is in Player.Bas:
B4X:
Sub ImportHeader(Header() As Short) As String
...
     Main.SetzeSongTitelLabel(BAS.ReadNameFromHeader(50,20,Header))
...

And this is in Main:
B4X:
public Sub SetzeSongTitelLabel(NeuerTitel As String )
    Log("setze songname=" & NeuerTitel)
    SongNameLabel.Text= NeuerTitel
    Log("NEU=" & SongNameLabel.Text )
End Sub

The SetztSongTitelLabel is working as expected, when I call it from Main directly


And even stranger... If I divide the calling function into two lines...
B4X:
Sub ImportHeader(Header() As Short) As String
...
    Dim a As String=BAS.ReadNameausHeader(50,20,value)
    Main.SetzeSongTitelLabel(a)
...
... I get no error message but this loggging:
setze songname=BlueChampagne
NEU=BlueChampagne


.In both cases the Label Text does not change on the app.
 
Last edited:

Midimaster

Active Member
Licensed User
Oh thank you. This means that the bug is much earlier before this. I really use a library to unzip the file, which contains the header: ArchiverPlusZip. The only difference betwenn B4A version and B4J version seems to be, that I have to define
B4X:
    Zip.ZipExecutionMode = Zip.ZIP_EXECMODE_ASYNCHRONOUS

Because of this behavior I tried to wait for the Event ZipEvent_ZipResult in my calling function
B4X:
Public Sub LoadSong(file As String )
    file=DeZip(file,"")
    Log("B time point " & (DateTime.Now-GlobalZeit))
    Wait For ZipEvent_ZipResult(Result As Int, ErrorMsg As String)
    Log("C time point " & (DateTime.Now-GlobalZeit))
...

Sub DeZip(file As String) As String
    GlobalZeit=DateTime.Now
    Log("Zip START ")
    Zip.ZipExecutionMode = Zip.ZIP_EXECMODE_ASYNCHRONOUS
    Zip.DecryptZipWithString(ZipPasswort)
    Dim ZipFile As String = File.Combine( DataFolder, file)
    Dim lstEntries As List = Zip.ListZipEntries(ZipFile)
    Dim ZipInfo As ArchiverZipInfo = lstEntries.Get(0)
    Dim SourceDatei=ZipInfo.FileName
    Zip.UnZipFile2(ZipFile,SourceDatei,DataFolder,SourceDatei,"ZipEvent")
    Log("A time point" & (DateTime.Now-lZeit ))
    Return SourceDatei
End Sub


Sub ZipEvent_ZipResult(Result As Int,Error As String )
    Log("Zip RESULT" & Result & " " & Error)
    Log("D time point D (finished)" & (DateTime.Now-GlobalZeit ))
End Sub

Sub ZipEvent_ZipProgression(Operation As Int, Filename As String, Percent As Float )
      '  Log("working " & Operation & " " & Percent & "%")
End Sub

The time points "A" "B" are logged very fast and after a long time the time point "C" loggs too. (The time point D never loggs.)

I thought this reaching of time point "F" means that the process has finished. But if I use the code like this I get this problems in setting the Label.Text

Without Dezipping I receive no error messages.

Is my use of the Wait For wrong?
 
Upvote 0
Top