Bug? [B4A] Instructions following Wait For are not executed when Sleep() has been called in same Sub

GianniGntl

Member
Licensed User
Summary:
In a B4A class, I need a Sub to execute, among other instructions, Sleep() and then a Wait For (a long task), but subsequent lines of code are never executed; removing the Sleep() is not an option (doing so, instructions are executed as expected).

Reproduction Steps:
  1. Install and launch B4A version (12.50)
  2. Set path to jdk-1.8\bin\javac.exe (also tried jdk-17.0.5 and jdk-19.0.2)
  3. Set path to android-33\android.jar (also tried android-33)
  4. Open the project in attached zip (or copy and paste following code in a Default New Project, adding a second button to Layout.bal)
  5. Compile and run the project
  6. Observe output in log window after pressing either button
Actual Behavior:
==================
Waiting for LongTask
C Started
C Done

Expected Behavior:
==================
Waiting for LongTask
C Started
C Done
*** Use Successfull ***

- Notes: Issue occurs on real device (Redmi Note 8 Pro - Android 11) and emulator (Platform_30_google_apis_playstore). I don't attach original code, it is more complex and part of a bigger project, so I just recreate the issue with a minimal number of lines of code
- Additional information: Putting the Sub in Activity ad calling it, it works. Using same class in B4J, code executed as expected (no bugs).

Main:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

#BridgeLogger: True

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Dim bug As ReproduceBug
End Sub

Sub Activity_Create(FirstTime As Boolean)
    bug.Initialize
    Activity.LoadLayout("Layout")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_Click
    bug.Use(False)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

Sub Button2_Click
    bug.Use(True)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

ReproduceBug.bas:
Sub Class_Globals
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   
End Sub

Public Sub Use (sleeping As Boolean)
    If sleeping Then
        Sleep(0)
    End If
   
    Log("Waiting for LongTask")
    Wait For (LongTask) Complete (success As Boolean)

    'Bug: if sleeping = True, following code wont execute
    If success Then
        Log("*** Use Successfull ***")
    Else
        Log("*** Use Failed ***")
    End If
End Sub

Private Sub LongTask () As  ResumableSub
    Log("C Started")
    Sleep(100)
    Log("C Done")
    Return True
End Sub
 

Attachments

  • Project.zip
    3.3 KB · Views: 67

DonManfred

Expert
Licensed User
Longtime User
as soon as you use sleep or waitfor the sub becomes a resumeable sub.
"use" is a resumeable sub to and need to be handled like one.

B4X:
Sub Button1_Click
    Wait For (bug.Use(False)) Complete (success As Boolean)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

Sub Button2_Click
    'bug.Use(True)
    Wait For (bug.Use(True)) Complete (success As Boolean)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

B4X:
Public Sub Use (sleeping As Boolean) As ResumableSub
    If sleeping Then
        Sleep(0)
    End If
   
    Log("Waiting for LongTask")
    Wait For (LongTask) Complete (success As Boolean)

    'Bug: if sleeping = True, following code wont execute
    If success Then
        Log("*** Use Successfull ***")
    Else
        Log("*** Use Failed ***")
    End If
    Return success
End Sub

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
Waiting for LongTask
C Started
C Done
*** Use Successfull ***
 

GianniGntl

Member
Licensed User
as soon as you use sleep or waitfor the sub becomes a resumeable sub.
"use" is a resumeable sub to and need to be handled like one.

B4X:
Sub Button1_Click
    Wait For (bug.Use(False)) Complete (success As Boolean)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

Sub Button2_Click
    'bug.Use(True)
    Wait For (bug.Use(True)) Complete (success As Boolean)
    xui.MsgboxAsync("Hello world!", "B4X")
    Log("==================")
End Sub

B4X:
Public Sub Use (sleeping As Boolean) As ResumableSub
    If sleeping Then
        Sleep(0)
    End If
 
    Log("Waiting for LongTask")
    Wait For (LongTask) Complete (success As Boolean)

    'Bug: if sleeping = True, following code wont execute
    If success Then
        Log("*** Use Successfull ***")
    Else
        Log("*** Use Failed ***")
    End If
    Return success
End Sub

Hi DonManfred, thanks for your reply.

Tried your code, the issue remains: Wait For (bug.Use(True)) Complete (success As Boolean) never completes.
Anyway:
  • The way you suggest is not applicable to my case because I don't have control over the calling code (imagine the Sub in question is B4XPage_Created or B4XPage_Appear)
  • I really don't need a ResumableSub as there isn't a return value.
  • B4J version, whose java sub generated code is similar, works as expected. Maybe problem resides in B4A waiting queue message manager.
Regards
 

agraham

Expert
Licensed User
Longtime User
I see it too but can't explain it. You seem to be able to WaitFor a Resumable Sub in main when calling a Resumable Sub in a class instance OK. But if that Resumable Sub in the class instance in turn does a Wait For another Resumable Sub in the class instance then that Wait For in the first Resumable Sub never Completes.

As it works in B4J it does look like a "feature" in B4A, whether intrinsic to the message loop handling or a generated code problem I can't determine.
 

Chris2

Active Member
Licensed User
I get something weird when playing with your example.
I see the problem at first, but if I copy and paste the LongTask sub, naming the copy LongTask2 for example, and then call LongTask2 from Use instead, it works!

So, I end up with
B4X:
Public Sub Use (sleeping As Boolean)
    If sleeping Then
        Sleep(0)
    End If
 
    Log("Waiting for LongTask")
    Wait For (LongTask2) Complete (success As Boolean)

    'Bug: if sleeping = True, following code wont execute
    If success Then
        Log("*** Use Successfull ***")
    Else
        Log("*** Use Failed ***")
    End If
End Sub

Private Sub LongTask () As  ResumableSub
    Log("C Started")
    Sleep(100)
    Log("C Done")
    Return True
End Sub


Private Sub LongTask2 () As  ResumableSub
    Log("C Started")
    Sleep(100)
    Log("C Done")
    Return True
End Sub
... and it works.
 

Chris2

Active Member
Licensed User
I think that is a red herring of some sort, though I don't know why. If I change the name of LongTask to LongTask2 I still don't get the Complete event raised
It might well be a red herring, but just in case, here's exactly what I'm doing:
1. Open the @GianniGntl project example.
2. Connect to B4A bridge.
3. Run the app in Debug, allow installation on phone
4. Click 'BUGGED' button - issue as reported by @GianniGntl. OK the msgbox.
5. While app still 'live', rename LongTask to LongTask2, change the line in 'Use' sub to suit, and save to 'Hot Swap' the code.
6. Click 'BUGGED' button - allOK,

B4X:
Logger connected to:  ........
--------- beginning of main
Copying updated assets files (1)
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
==================
Waiting for LongTask
C Started
C Done
==================               <- make change ( LongTask to LongTask2) and save/HotSwap
Waiting for LongTask
C Started
C Done
*** Use Successfull ***
** Activity (main) Pause, UserClosed = false **
 
Last edited:

Chris2

Active Member
Licensed User
Please try to reproduce it with B4XPages.
I've only tried it quickly, but following the steps in my post #7 I cannot recreate the issue in a B4XPages app.
I can still recreate it and 'solve' it using the steps in post #7 consistantly in a non-B4XPages app though.
 
Top