Android Tutorial DoEvents deprecated and async dialogs (msgbox)

Discussion in 'Tutorials & Examples' started by Erel, May 16, 2017.

  1. Erel

    Erel Administrator Staff Member Licensed User

    Starting from B4A v7.0 the following warning will appear for DoEvents calls:
    DoEvents is deprecated. It can lead to stability issues. Use Sleep(0) instead (if really needed).

    The purpose of DoEvents was to allow the UI to be updated while the main thread is busy. DoEvents which shares the same implementation as the modal dialogs implementation, is a low level implementation. It accesses the process message queue and runs some of the waiting messages.

    As Android evolved, the handling of the message queue became more sophisticated and fragile.
    The reasons for deprecating DoEvents are:

    1. It is a major source for instability issues. It can lead to hard to debug crashes or ANR (application not responding) dialogs. Note that this is also true for the modal dialogs (such as Msgbox and InputList).
    2. There are better ways to keep the main thread free. For example use the asynchronous SQL methods instead of the synchronous methods.
    3. It doesn't do what many developers expect it to do. As it only handles UI related messages, most events could not be raised from a DoEvents call.
    4. It is now possible to call Sleep to pause the current sub and resume it after the waiting messages are processed. Sleep implementation is completely different than DoEvents. It doesn't hold the thread. It instead releases it while preserving the sub state.
    Unlike DoEvents which only processed UI related messages, with Sleep all messages will be processed and other events will be raised.
    (Note that using Wait For to wait for an event is better than calling Sleep in a loop.)

    With that said, DoEvents is still there and existing applications will work exactly as before.

    Dialogs

    Modal dialogs = dialogs that hold the main thread until the dialog is dismissed.

    As written above, modal dialogs share the same implementation as DoEvents. It is therefore recommended to switch to the new async dialogs instead. Using Wait For it is really a simple change:

    Instead of:
    Code:
    Dim res As Int = Msgbox2("Delete?""Title""Yes""Cancel""No"Null)
    If res = DialogResponse.POSITIVE Then
      
    End If
    You should use:
    Code:
    Msgbox2Async("Delete?""Title""Yes""Cancel""No"NullFalse)
    Wait For Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
       
    '...
    End If
    Wait For doesn't hold the main thread. It instead saves the current sub state and releases it. The code will resume when the user clicks on one of the dialog buttons.
    The other similar new methods are: MsgboxAsync, InputListAsync and InputMapAsync.

    With the exception of MsgboxAsync, the new methods also add a new cancelable parameter. If it is true then the dialog can be dismissed by clicking on the back key or outside the dialog. This is the default behavior of the older methods.

    As other code can run while the async dialog is visible, it is possible that multiple dialogs will appear at the same time.
    If this case is relevant for your app then you should set the sender filter parameter in the Wait For call:
    Code:
    Dim sf As Object = Msgbox2Async("Delete?""Title""Yes""Cancel""No"NullFalse)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
       
    '...
    End If
    This allows multiple messages to be displayed and the result events will be handled correctly.

    Bug in B4A v7.00 / 7.01 - Async dialogs should not be used in classes as the Result event will be raised in the Activity instead of the class module. This is fixed for the next update.
     
    Last edited: May 28, 2017
  2. Star-Dust

    Star-Dust Expert Licensed User

    Thank you Mr Erel.

    Considering that there are some libraries or classes that use DoEvents to wait for the outcome of an event, as it has pointed out to objects similar to the MsgBox or other dialog objects,
    Of course they must be updated for version 7 with the comand wait.

    My question is this.
    For the future, do you need to produce libraries or classes for versions 7 that use wats or earlier versions that use DoEvents?
    Is a specific API required to run the wait command?
    Compiled libraries with B4A version 7 using the wait command can be used with previous versions of B4A?
     
    Last edited: May 16, 2017
  3. Erel

    Erel Administrator Staff Member Licensed User

    Existing libraries will continue to work as DoEvents is still available.

    If your code uses Wait For and you compile it to a library then it will only work in B4A v7+.
    I wouldn't use a library that calls DoEvents. As explained above DoEvents should be avoided.
     
    pesquera and eps like this.
  4. Star-Dust

    Star-Dust Expert Licensed User

    Thank's
     
  5. mrred128

    mrred128 Active Member Licensed User

    Why not just (internally) change the DoEvents code to that of sleep? It would be transparent and silently move everything forward.
     
    AndrewKing, MikeMax and Kevin like this.
  6. Erel

    Erel Administrator Staff Member Licensed User

    It will not be transparent. See the resumable subs tutorial: [B4X] Resumable Subs - Sleep / Wait For

    1. Resumable subs cannot return a value.
    2. The code flow is different. Calling Sleep or Wait For is equivalent to calling Return from the caller sub perspective.
     
    Last edited: May 22, 2017
    pesquera and MarcoRome like this.
  7. mrred128

    mrred128 Active Member Licensed User

    So much for easy... :)
     
  8. Widget

    Widget Well-Known Member Licensed User

    Erel, when you say:
    1. Resumable subs cannot return a value.
    2. The code flow is different. Calling Sleep or Wait For is equivalent to calling Return from the caller sub perspective.​

    1) That rule applies all functions and subs that modify parameters like Map or List, correct?

    2) Will CustomListView be changed to remove the "DoEvents" entirely?
    (Some of the Subs like getHeight, getWidth are functions)

    3) Are there built in conditional variables for B4X version number so it can be used as:

    Code:
    #IF $VER > 6.5
    ...
    #END IF

    #
    IF $VER = 7
    ..
    #END IF


    #
    IF $PROD = "B4A"
      .. B4A Code ..  
    #ELSE
      #
    IF $PROD = "B4I"
         ... B4i Code ...
      
    #END IF
    #END IF
    TIA
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    1) You can do everything that you like in the resumable sub, including modifying lists or maps or global variables, except of calling Return <value here>.

    2) There are no DoEvents calls in the latest version of CustomListView. In the past DoEvents was used to immediately change the scroll position. This is no longer required as you can instead use ScrollView.ScrollToNow.

    3) Product symbols are available: https://www.b4x.com/android/forum/t...mpilation-build-configurations.40746/#content
    There are no built-in symbols for versions.
     
    Widget likes this.
  10. ilan

    ilan Expert Licensed User

    Thank you very much for this erel. This is a very impotant addition to b4a.

    I have a small question please.

    Do time/date dialogs also hold the main thread until the user response?

    If yes is there a similar solution for date and timedialog?

    Thank you
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    The dialogs from the Dialogs library are modal (like Msgbox). I plan to update the Dialogs library and provide async methods.
     
    mrred128 and ilan like this.
  12. ilan

    ilan Expert Licensed User

    the resumable sub function is really awesome. i use it in many cases and works great. it saves a lot headache using csu instead.

    i just dont understand something in this code:

    Code:
    Msgbox2Async("Delete?""Title""Yes""Cancel""No"NullFalse)
    Wait For Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
       
    '...
    End If
    in the wait for line you say in the code to wait for the sub Msgbox_Result (Result As Int)

    so in the beginning i created this sub manually and returned the value but then i noticed that i don't need to create it but i don't understand from where the result is returned??

    is it returned from this line? is like putting 2 subs in 1 sub together and when the user hit the msgbox button it will return from that line?
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    More correct to say that it will wait for the Msgbox_Result event.

    Yes.
     
  14. derez

    derez Expert Licensed User

    What do you do with this sub that has to return a value ?
    Code:
    Sub Activity_KeyPress (KeyCode As Int) As Boolean
        
    If KeyCode = KeyCodes.KEYCODE_BACK Then
            
    Dim k As Int = Msgbox2(......)
            
    If k =  DialogResponse.NEGATIVE Then Return True
        
    End If
        
    Return False
    End Sub
     
  15. ilan

    ilan Expert Licensed User

    maybe like this:

    Code:
    Private returnValue As Boolean

    '...

    Sub Activity_KeyPress (KeyCode As Int) As Boolean
        
    If KeyCode = KeyCodes.KEYCODE_BACK Then
            msgb(
    "Exit App?""Exit")
            
    If returnValue Then Return True
        
    End If
        
    Return False
    End Sub

    Sub msgb(txt As String, title As String)
        returnValue = 
    False
        
    Dim sf As Object = Msgbox2Async(txt, title, "Yes""Cancel""No"NullFalse)
        
    Wait For (sf) Msgbox_Result (Result As Int)
        
    If Result = DialogResponse.POSITIVE Then
            returnValue = 
    True
        
    End If
    End Sub
     
    derez likes this.
  16. Erel

    Erel Administrator Staff Member Licensed User

    This code is simpler and doesn't use a global variable:
    Code:
    Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
       If KeyCode = KeyCodes.KEYCODE_BACK Then
         ShouldCloseActivity
         
    Return True 
       
    End If
       
    Return False
    End Sub

    Private Sub ShouldCloseActivity
       
    Dim sf As Object = Msgbox2Async(...)
       
    Wait For (sf) Msgbox_Result (Result As Int)
       
    If Result Then Activity.Finish
    End Sub
     
    inakigarm, lemonisdead and derez like this.
  17. derez

    derez Expert Licensed User

    Code:
    If Result = DialogResponse.POSITIVE Then Activity.Finish
     
    ilan likes this.
  18. ilan

    ilan Expert Licensed User

    i wrote my code like this because this is a way to return a value.

    if its only to perform an action like finish the app then erels solution is better but unfortunately if you want to return a value i dont see a way without using a global variable (from a resumeable sub).
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    It is not possible to show a modal dialog or call DoEvents inside the Activity_KeyPress event. Starting from Android 4.3 it causes a low level crash.

    As I knew that this sub is mainly used with code similar to the one you posted, I added a check for the back key and it actually uses a solution similar to CallSubDelayed and then closes the activity based on the return value. If you try to show a modal dialog when the pressed key is not the back key then it will crash.
    You can see it mentioned here: https://www.b4x.com/android/help/views.html#activity
    The point is that async dialogs are always better (safer) than the modal dialogs.

    You don't need a global variable. You need to return the value with CallSubDelayed.
    https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/page-3#post-506651
     
    ilan likes this.
  20. Computersmith64

    Computersmith64 Well-Known Member Licensed User

    Hi Erel - I have exactly this issue in a project I'm currently working on. Any idea when the fix will be released?

    - Colin.
     
Loading...
  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