Android Question Change DoEvents in ClsExplorer

asales

Expert
Licensed User
Longtime User
I'm trying to update this code of the File Explorer class:
https://www.b4x.com/android/forum/threads/class-file-explorer-with-visualization.19003/
to use Sleep(0) instead the DoEvents.

I'm stopped in this part of the code, because if I use Sleep(0) (or 100 or 1000) don't works.
B4X:
Do While WaitUntilOK
   ' Main loop - we wait until the OK btn is pressed or the back key is used
   DoEvents
Loop
I think this will be useful to @Robert Valentino too, that posted this thread (if him don't found an answer):
https://www.b4x.com/android/forum/threads/clsexplorer-without-doevents.88865/

Thanks in advance for any tips.
 

Claudio Oliveira

Active Member
Licensed User
Longtime User
This code is inside private sub CommonExplorer, which is called by public subs Explorer or Explorer2. In both cases, the call to CommonExplorer is the very last statement before End Sub.
Unlike DoEvents, which interrupts processing and allows UI updating, Sleep() returns to the calling sub which, in this particular case, immediatly ends. Maybe this interrupts the code flow.
It's just a guess. I'm absolutely not sure, but even if I'm wrong, I do believe this is a good starting point and most certainly I'll learn a bit more about Sleep, Wait For and resumable subs...
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I haven't seen the relevant code however the correct way to use sleep without changing the current code flow is by waiting for the resumable sub to complete.

B4X:
Sub BusySub As ResumableSub
 Do While WaitUntilOK
  Sleep(10)
 Loop
 Return True
End Sub

'call it like this:
Wait For (BusySub) Complete (Success As Boolean)

This is explained in the resumable subs video tutorial.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Do you have any problem with DoEvents?
The code suggested by Erel seems ok but it is untested.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
I tried the code suggested by Erel and it does not do what's expected because the code is not blocked. When you call the explorer, the code after this call executes immediately. A possible solution is to create a Result event and to wait for this event in the calling code but that would break all projects using the Explorer class.
Until now, I was not able to replace the DoEvents calls in my different libraries/classes/apps by a Sleep/WaitFor. Moreover I never had the slightest problem with these DoEvents so I don't understand why it is now undesirable.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
ntil now, I was not able to replace the DoEvents calls in my different libraries/classes/apps by a Sleep/WaitFor
It is difficult to reproduce the issues with DoEvents and modal dialogs. However many of the Google Play crash reports that include nativePollOnce are related to them: https://www.b4x.com/android/forum/pages/results/?query=nativePollOnce

I was not able to replace the DoEvents calls in my different libraries/classes/apps by a Sleep/WaitFor
Sleep behavior is indeed different than DoEvents.
If you used DoEvents to allow the UI to be kept responsive while doing a lengthy task then you can replace it with Sleep(0), make that sub return ResumableSub and call it with Wait For (LongSub) Complete (ReturnValue As Boolean)
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
It is difficult to reproduce the issues with DoEvents and modal dialogs. However many of the Google Play crash reports that include nativePollOnce are related to them: https://www.b4x.com/android/forum/pages/results/?query=nativePollOnce
https://www.b4x.com/android/forum/pages/results/?query=nativePollOnce
DoEvents is maybe complicated to use because there are cases, for example, where it cannot be used directly and must be called via CallSubDelayed (e.g. it will crash your app if you call it directly in a libGDX event, as this event is not run on the main thread). But who is to blame? The programmer or the function?

The message saying to replace DoEvents in the Log window worries many users. Alas, I have nothing to answer to them. I'm unable to replace these DoEvents by something similar.

I think that I understand how Sleep and WaitFor work (and I use both of them in my code). Nethertheless, I'm unable to replace DoEvents successfully (in ULV, in my Archiver libs, in BetterDialogs, in FileExplorer...), either because I need to block the flow where the call is made (the case discussed above) or because I need to update the UI from a progression event. For the first case, I can change the philosophy of the code and use an event to return the result of the call. This way, I can use Wait For to stop the flow and wait for the result. But in the latter case, which is the most current in my code, I do not see an alternative. Example:
B4X:
Sub PerformMainOp
   DisplayTask("Unzip toto")
   Arc.Unzip("toto")

   DisplayTask("Unzip tata")
   Arc.Unzip("tata")

   DisplayTask("Unzip tutu")
   Arc.Unzip("tutu")
End Sub

Sub DisplayTask(Text As String)
   'Displays the current task
   lblTask.Text = Text
   DoEvents 'Forces an update of the UI
End Sub

Sub UltArc_Progress(Bytes As Long)
   DisplayProgression(Bytes & "/" & TotalSize)
End Sub

Sub UpdateLabel(Lbl As Label, NewText As String)
   Lbl.Text = NewText
End Sub

Sub DisplayProgression(Text As String)
   'Displays the current progression
   CallSubDelayed3(Me, "UpdateLabel", lblProgression, Text) 'Allows to update the label from any thread
   DoEvents
End Sub
 
Upvote 0

XbNnX_507

Active Member
Licensed User
Longtime User
if (wait for) works the way it should be then this should work...

B4X:
Sub PerformMainOp
   DisplayTask("Unzip toto")
   Arc.Unzip("toto")

   DisplayTask("Unzip tata")
   Arc.Unzip("tata")

   DisplayTask("Unzip tutu")
   Arc.Unzip("tutu")
End Sub

Sub DisplayTask(Text As String)
   'Displays the current task
   lblTask.Text = Text
   'DoEvents 'Forces an update of the UI
   wait for (RefreshUI) Complete ( Value as Object )
End Sub

Sub RefreshUI As ResumableSub
    Sleep    ( 0 )
    Return     Null
End Sub

Sub UltArc_Progress(Bytes As Long)
   DisplayProgression(Bytes & "/" & TotalSize)
End Sub

Sub UpdateLabel(Lbl As Label, NewText As String)
   Lbl.Text = NewText
End Sub

Sub DisplayProgression(Text As String)
   'Displays the current progression
   CallSubDelayed3(Me, "UpdateLabel", lblProgression, Text) 'Allows to update the label from any thread
   wait for (RefreshUI) Complete ( Value as Object )
End Sub
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
It's something I tried. No update at all. The label remains empty.
Note that there's a second DoEvents in DisplayProgression.

EDIT: changing the Sleep value to something else than 0 does not change anything.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…