B4J Question Sleep() causes unexpected program exit?

Discussion in 'B4J Questions' started by Jeffrey D. Spiegler, Apr 18, 2019.

  1. Jeffrey D. Spiegler

    Jeffrey D. Spiegler Member Licensed User

    Hello folks, thanks in advance...

    I'm writing/running some very small non-UI programs under B4J, hoping that the core stuff I'm playing with is the same for B4A, as that is my ultimate goal, to develop an Android app.

    So, I was playing around with timers, getting familiar with those.In my 'x_Tick' loop (1000 ms delay), I just increment a global integer 'count' variable. Outside, I check if 'count' is less than 10 -- if it is, I Log the value of count, then Sleep for 1000 ms; otherwise, the loop ends. Trouble is, if and when I call Sleep, the program ends. Got rid of the timer stuff (we'll come back to you later...), to focus on the Sleep trouble, so my code is the following:

    'Non-UI application (console / server application)
    #Region Project Attributes
    #MergeLibraries: True
    #End Region

    Sub Process_Globals
    End Sub

    Sub AppStart (Args() As String)
    Private count As Int = 121

    Log( "A: " & count )

    Log( "in Catch" )
    End Try

    Log( "B: " & count )
    count = count + 1
    End Sub

    'Return true to allow the default exceptions handler to handle the uncaught exception.
    Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
    End Sub

    So, I see the "Log A: 121" message in the output, but not the "B:" one. There are no error or warning messages, either building or running. If I comment out the "Sleep( 1 )" statement, I see the "B:" message, as well as the "A:" one. If I put the Try/Catch block (and few lines below, the "Loop" statement ends up under the line that increments count) into a Do While count < 10 loop, it runs fine, count goes from 1-10 with Sleep commented out; otherwise, I see the "A: 121" message just once (first time through the loop), then nothing (no "B: 121", no messages with higher values of count); I just get what seems to be this normal exit message (?):

    Program terminated (StartMessageLoop was not called).

    Tried calling Sleep with several different delay values: 0, 1, 10. 100, 1000, 10000 == all behaved the same, terminating execution.

    Added the Try/Catch block after I was completely puzzled -- the Catch block never gets called, with or without Sleep() commented out.

    Tried declaring count with 'Dim" instead of 'Private' -- no difference.

    Any ideas? Something very basic I'm missing/overlooking?

  2. Erel

    Erel Administrator Staff Member Licensed User

    This is expected.

    Also expected.
    Also expected.
    1. Use [code]code here...[/code] tags when posting code.
    2. You forgot the very first rule of Sleep and Wait For. From the calling method perspective they are equivalent to calling Return. This means that the program returns from AppStart and ends as you haven't started a message loop (this is a non-ui program).

    If you haven't watched the resumable subs video tutorial then you should: https://www.b4x.com/etp.html

    Sub Process_Globals
    End Sub

    Sub AppStart (Args() As String)

    End Sub

    Sub DoSomething
    Dim count As Int = 121
    count = count + 
    End Sub
    Harris and José J. Aguilar like this.
  3. Jeffrey D. Spiegler

    Jeffrey D. Spiegler Member Licensed User

    Hello Erel,

    Thanks for the tip re the <code>...</code> (actually, is it angle brackets or square brackets? or either, or no brackets?), I will start to use them.

    I did have the feeling I was documenting known behavior as I was writing my post, but I wanted to show that I had tried what I could think of on my own to get it to work, before posting.

    Watched the video, that helped. Although the use of StartMessageLoop was not quite obvious. Your example in the video didn't need StartMessageLoop because it had a UI? And anything with a UI implicitly (or even explicitly) starts the message loop code to process UI events?

    Changed my little program to basically match the structure that you had in your reply to me, it all worked as expected, thanks.

    I had some code after StartMessageLoop (just a call to Log()) that never executed. So I presume that StartMessageLoop never returns to its caller?

    In the hover over help shown when I typed in StartMessageLoop I saw that there is also a StopMessageLoop Sub. Is it required or good practice to call this before exiting the application, if I've called StartMessageLoop? Or the OS will clean this up? I tried both ways, both seemed to work.

    Thanks again, thanks much,
  4. Erel

    Erel Administrator Staff Member Licensed User

    Square brackets.

    StartMessageLoop is only required in non-UI projects. All other types of apps (including B4A and B4i) start with a message loop.

    It returns after you call StopMessageLoop.

    It is not required if you call ExitApplication.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice