B4J Question Sleep() causes unexpected program exit?

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
#CommandLineArgs:
#MergeLibraries: True
#End Region

Sub Process_Globals
End Sub

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

Log( "A: " & count )


Try
Sleep(1)
Catch
Log( "in Catch" )
Log(LastException)
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?

Thanks,
Jeff
 

Erel

Administrator
Staff member
Licensed User
Tried calling Sleep with several different delay values: 0, 1, 10. 100, 1000, 10000 == all behaved the same, terminating execution.
This is expected.

Added the Try/Catch block after I was completely puzzled -- the Catch block never gets called, with or without Sleep() commented out.
Also expected.
Tried declaring count with 'Dim" instead of 'Private' -- no difference.
Also expected.
Any ideas? Something very basic I'm missing/overlooking?
Yes.
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

Solution:
B4X:
Sub Process_Globals
End Sub

Sub AppStart (Args() As String)
 DoSomething
 StartMessageLoop

End Sub

Sub DoSomething
 
Dim count As Int = 121
Sleep(1)
count = count + 1
End Sub
 

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,
Jeff
 

Erel

Administrator
Staff member
Licensed User
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.
Square brackets.

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

So I presume that StartMessageLoop never returns to its caller?
It returns after you call StopMessageLoop.

Is it required or good practice to call this before exiting the application, if I've called StartMessageLoop?
It is not required if you call ExitApplication.
 
Top