Android Question Sleep(0) as alternative to DoEvents

Status
Not open for further replies.

LucaMs

Expert
Licensed User
I have read this statement:
You can call Sleep(0) for the shortest pause. This can be used to allow the UI to be refreshed. It is a good alternative to DoEvents (which doesn't exist in B4J and B4i and should be avoided in B4A).
I think that you cannot use Sleep(0) as an alternative to DoEvents, because anyway, even setting to 0 the duration of the sleep, control wil be returned (for micro-seconds, probably) to the calling routine.

An (stupid) example:

B4X:
Sub Activity_Resume
    For i = 1 To 10
        LogColor("I : " & i, Colors.Red)
        Show
    Next
End Sub

Sub Show
    For j = 1 To 100
        Label1.Text = j
        LogColor("J : " & j, Colors.Blue)
        Sleep(0)
    Next
End Sub
The result of this code is not what you wanted. If you use DoEvents (I tried also using VB.NET) you get the "right" behavior.
 
Last edited:

Erel

Administrator
Staff member
Licensed User
control wil be returned (for micro-seconds, probably) to the calling routine.
As explained in the tutorial, from the calling sub perspective, Sleep or Wait For are equivalent to Return. The code will not return for microseconds it will return and execute any remaining code.

This however doesn't mean that Sleep is not a good alternative to DoEvents. This means that you need to use it correctly.
https://www.b4x.com/android/forum/t...d-and-async-dialogs-msgbox.79578/#post-505390

If you want to call a resumable sub and wait for it to complete before you continue: https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/page-2#post-499130
 

Erel

Administrator
Staff member
Licensed User
If Sleep(0) was a valid alternative to DoEvents
Sleep(0) is not a transparent replacement to DoEvents. As I wrote in this thread and in others the behavior is different (and the implementation is completely different).
You can use it to solve the same problem that you used DoEvents for. You can use it to allow the UI to refresh without splitting the code into multiple subs. You can also use Sleep for many other tasks.

wrong link?
In that post I explained why Sleep(0) is not a transparent replacement to DoEvents.

This is a clarifier: to replace DoEvents you have to use Sleep in pairs with "Wait For".
No. It depends on your specific code.
Example:
B4X:
Sub Button1_Click
 For i = 1 To 10
   Label1.Text = i
   Sleep(100) 'don't use 0 if you want the user to see the changes
 Next
End Sub
As a general rule prefer to make the sleep or wait for calls in the parent sub instead. If needed you can combine it with Wait For.

With that said, DoEvents is still available. You are not forced to use Sleep. Personally I will never write new code with DoEvents but it is a free world ;)
 

LucaMs

Expert
Licensed User
I think my fault is that I'm not exactly talking about DoEvents but actually about how to create a pause within a routine (or "blocking" ONLY the sw flow) and at the same time having the ability to update the GUI.

VB.Net's DoEvents allows you to create this kind of routine, B4A's DoEvents is different.

I'm trying to create that kind of "method":
Wait(1000) ' pauses THE APP (without blocking the process) for one second but at the same time allowing the GUI update.

The following code produces the right log (the same you get using VB.Net) but the GUI is not updated.
B4X:
Sub Activity_Resume
   For i = 1 To 3
     LogColor("I : " & i, Colors.Red)
     Show
   Next
End Sub

Sub Show
   For j = 98 To 100
     LogColor("J : " & j, Colors.Blue)
     Label1.Text = j
     Wait(1000) ' here I wish wait for one second, with GUI refresh
   Next
End Sub

' ******************************************************
' ***  These two routines should do what "I" need.
' ***  Putting them in a simple library, you could have
' ***  a Wait command which does what I mean.
' ***  But the GUI will not be updated!
Public Sub Wait(Duration As Long)
   WaitHelper(Duration)
   Wait For WaitHelper_Completed
End Sub
Private Sub WaitHelper(Duration As Long)
   Sleep(Duration)
   CallSubDelayed(Me, "WaitHelper_Completed")
End Sub
' ******************************************************
 
Last edited:

lemonisdead

Well-Known Member
Licensed User
@LucaMs

Do you mean that ? The events seem to be sent afterward. I will try another solution.
1.png

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Label1.Initialize("Label1")
   
    Activity.AddView(Label1,10%x,10%y,80%x,60dip)
End Sub

Sub Activity_Resume
    For i = 1 To 3
        LogColor("I : " & i, Colors.Red)
        Show
    Next
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Show
    For j = 98 To 100
        LogColor("J : " & j, Colors.Blue)
        Label1.Text = j
        Label1.Invalidate
        Wait(2000,J) ' here I wish wait for one second, with GUI refresh
    Next
End Sub


' ******************************************************
' ***  These two routines should do what "I" need.
' ***  Putting them in a simple library, you could have
' ***  a Wait command which does what I mean.
' ***  But the GUI will not be updated!
Public Sub Wait(Duration As Long,J As Int)
    WaitHelper(Duration,J)
    Wait For WaitHelper_Completed
End Sub

Private Sub WaitHelper(Duration As Long,J As Int)
    Dim Now As Long
    Now=DateTime.now
    Log($"WaitHelper received: ${Duration} for loop: ${J}"$)
    Sleep(Duration)
    Log($"WaitHelper slept: ${DateTime.Now-Now} ms"$)
    CallSubDelayed(Me, "WaitHelper_Completed")
End Sub
' ******************************************************
 

lemonisdead

Well-Known Member
Licensed User
This seems to do it @LucaMs

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Label1.Initialize("Label1")
 
    Activity.AddView(Label1,10%x,10%y,80%x,60dip)
End Sub

Sub Activity_Resume
    For i = 1 To 3
        LogColor("I : " & i, Colors.Red)
        Show
    Next
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Show
    For j = 98 To 100
        LogColor("J : " & j, Colors.Blue)
'        Wait(2000,J) ' here I wish wait for one second, with GUI refresh
        Label1.Text = j
        WaitHelper(2000,j)
        Wait For WaitHelper_Completed
        Sleep(0)
    Next
End Sub


' ******************************************************
' ***  These two routines should do what "I" need.
' ***  Putting them in a simple library, you could have
' ***  a Wait command which does what I mean.
' ***  But the GUI will not be updated!
'Public Sub Wait(Duration As Long,J As Int)
'    WaitHelper(Duration,J)
''    Wait For WaitHelper_Completed
'End Sub

Private Sub WaitHelper(Duration As Long,J As Int)
    Dim Now As Long
    Now=DateTime.now
    Log($"WaitHelper received: ${Duration} for loop: ${J}"$)
    Sleep(Duration)
    Log($"WaitHelper slept: ${DateTime.Now-Now} ms"$)
    CallSubDelayed(Me, "WaitHelper_Completed")
End Sub
' ******************************************************
 
Last edited:

LucaMs

Expert
Licensed User
I did not launch your code but it is not what I would like to get.
I would like a single line of code to do the job:
Wait (X)

(If this was a b4x keyword it would be better, of course)
 

LucaMs

Expert
Licensed User
I can not find the reason why the 1000 ms pause does not occur.

B4X:
Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   Activity.LoadLayout("layMain")

   DateTime.TimeFormat = "mm:ss:SSS"
End Sub

Sub Activity_Resume
   For i = 1 To 3
LogWithTime("I : " & i, Colors.Red)
     Show
   Next
End Sub

Sub Show
   For j = 98 To 100
LogWithTime("J : " & j, Colors.Blue)
     Label1.Text = j
     Wait(1000) ' here I wish wait for one second, with GUI refresh
   Next
End Sub

' ******************************************************
' ***  These two routines should do what "I" need.
' ***  Putting them in a simple library, you could have
' ***  a Wait command which does what I mean.
' ***  But the GUI will not be updated!
Public Sub Wait(Duration As Long)
LogWithTime("Sub Wait", Colors.Black)
   WaitHelper(Duration)
   Wait For WaitHelper_Completed
End Sub

Private Sub WaitHelper(Duration As Long)
LogWithTime("Sub WaitHelper", Colors.Black)
   Sleep(Duration)
   CallSubDelayed(Me, "WaitHelper_Completed")
End Sub
' ******************************************************

Sub LogWithTime(Text As String, Color As Int)
   LogColor(DateTime.Time(DateTime.Now), Colors.Green)
   LogColor(TAB & Text, Color)
End Sub

[Thanks ALSO for the idea of using a spoiler, @lemonisdead :)]
 

Erel

Administrator
Staff member
Licensed User
You should use Sleep(1000) if you want to pause for a second.

B4X:
Sub Activity_Resume
     For j = 1 To 100
         Label1.Text = j
          LogColor("J : " & j, Colors.Blue)
         Sleep(1000)
      Next
End Sub
Correct code that updates a label every second (10 * 100 times):
B4X:
Sub Activity_Resume
    For i = 1 To 10
        LogColor("I : " & i, Colors.Red)
        For j = 1 To 100
           Label1.Text = j
            LogColor("J : " & j, Colors.Blue)
           Sleep(1000)
        Next
    Next
End Sub
As I previously explained if you want to wait for a resumable sub to complete then you need to use Wait For. So if you want to split it into two subs (which only makes it more complicate in this case) then the correct code is:
B4X:
Sub Activity_Resume
    For i = 1 To 10
        LogColor("I : " & i, Colors.Red)
        Show
        Wait For ShowComplete
    Next
End Sub

Sub Show

    For j = 1 To 100
           Label1.Text = j
            LogColor("J : " & j, Colors.Blue)
           Sleep(1000)
        Next
     CallSubDelayed(Me, "ShowComplete")
End Sub
Yes, I agree. Find it hard to believe there is no easy way of forcing the GUI to update while in a loop
Are you reading anything that I wrote?
You can use Sleep to pause the current sub and resume it after a specific specific period. This allows the UI to be updated.

The answer to the original question was posted in posts #2 and #6. If anyone has a different question or a similar question about resumable subs or any other topic then please start a new thread in the questions forum.
 
Last edited:
Status
Not open for further replies.
Top