Android Question Msgbox2Async why doesn't it wait

RB Smissaert

Well-Known Member
Licensed User
Longtime User
In a class I have this:

B4X:
Sub ShowMsg(strPrompt As String, _
         strTitle As String, _
         iTitleColour As Int, _
         iPromptColour As Int, _
         csPrompt As CSBuilder, _
         bmpIcon As Bitmap, _
         bCancelable As Boolean, _
       bWait As Boolean)
 
 Dim csTitle As CSBuilder
 
 'so like optional colour argument
 If iTitleColour = 0 Then
  iTitleColour = Colors.RGB(0, 0, 0)
 End If
 
 If iPromptColour = 0 Then
  iPromptColour = Colors.RGB(0, 0, 0)
 End If
 
 csTitle.Initialize.Color(iTitleColour).Append(strTitle).Pop
 
 'so csPrompt is like an optional argument, passing Null works fine
 If csPrompt.IsInitialized = False Then
  csPrompt.Initialize.Color(iPromptColour).Append(strPrompt).Pop
 End If
 
 'can pass Null for no icon
 Msgbox2Async(csPrompt, csTitle, "OK", "", "", bmpIcon, bCancelable)

 If bWait Then
  Wait For Msgbox_Result(iResult As Int)
 End If
 
End Sub

And I call this from Main like this:

B4X:
Sub DeleteDuplicateSQL
 Dim strSQL As String
 Dim lAffectedRows As Long
 Msgbox2Async("Are you sure to delete duplicate SQL from the table SQL?", _
     "Delete duplicate SQL from table SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = -1 Then
  strSQL = "DELETE FROM SQL WHERE ROWID NOT IN(" & _
     "SELECT MAX(ROWID) FROM SQL " & _
     "GROUP BY SQL)"
  General.SQL1.ExecNonQuery(strSQL)
  lAffectedRows = GetNumberOfChanges
  cEvents.ShowMsg("Duplicate rows deleted: " & lAffectedRows, _
      "Delete duplicate SQL from table SQL", 0, 0, Null, General.bmpIcon32, True, True)
 End If
 Msgbox2Async("Are you sure to delete duplicate SQL from the table RUN_SQL?", _
     "Delete duplicate SQL from table RUN_SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = -1 Then
  strSQL = "DELETE FROM RUN_SQL WHERE ROWID NOT IN(" & _
     "SELECT MAX(ROWID) FROM RUN_SQL " & _
     "GROUP BY SQL)"
  General.SQL1.ExecNonQuery(strSQL)
  lAffectedRows = GetNumberOfChanges
  cEvents.ShowMsg("Duplicate rows deleted: " & lAffectedRows, _
      "Delete duplicate SQL from table RUN_SQL", 0, 0, Null, General.bmpIcon32, True, True) 
 End If
End Sub

Problem is it doesn't wait for the first cEvents.ShowMsg and I see the second Msgbox2Async first and
the first cEvents.ShowMsg only later. Tried various constructions, eg with Sleep(0), but no success yet.
How should this be done?

RBS
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
When you're throwing up multiple async dialogs, you need to provide a reference to the ones you want to wait for. So try something like this:

B4X:
...

Private mb As Object = Msgbox2Async(csPrompt, csTitle, "OK", "", "", bmpIcon, bCancelable)

 If bWait Then
  Wait For (mb) Msgbox_Result(iResult As Int)
 End If
...

Depending on the order in which your dialogs are displaying, this might not the the correct one to be identifying, but you get the idea...

You can also look at the async dialogs tutorial here -> https://www.b4x.com/android/forum/t...cated-and-async-dialogs-msgbox.79578/#content

- Colin.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
When you're throwing up multiple async dialogs, you need to provide a reference to the ones you want to wait for. So try something like this:

B4X:
...

Private mb As Object = Msgbox2Async(csPrompt, csTitle, "OK", "", "", bmpIcon, bCancelable)

 If bWait Then
  Wait For (mb) Msgbox_Result(iResult As Int)
 End If
...

Depending on the order in which your dialogs are displaying, this might not the the correct one to be identifying, but you get the idea...

You can also look at the async dialogs tutorial here -> https://www.b4x.com/android/forum/t...cated-and-async-dialogs-msgbox.79578/#content

- Colin.

Thanks; I tried your idea, but same result.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
The most important rule of resumable subs:
Wait For or Sleep are equivalent to Return from the calling sub perspective.

Watch the resumable subs video tutorial and see how to handle it. The solution is simple.

Also see: [B4X] [XUI] B4XDialog - Custom dialogs

OK, thanks and have found this simple solution:

In Main:

B4X:
Sub DeleteDuplicateSQL
 Dim strSQL As String
 Dim lAffectedRows As Long
 Dim iResult As Int
 Msgbox2Async("Are you sure to delete duplicate SQL from the table SQL?", _
     "Delete duplicate SQL from table SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = -1 Then
  strSQL = "DELETE FROM SQL WHERE ROWID NOT IN(" & _
     "SELECT MAX(ROWID) FROM SQL " & _
     "GROUP BY SQL)"
  General.SQL1.ExecNonQuery(strSQL)
  lAffectedRows = GetNumberOfChanges
  wait for (cEvents.ShowMsg("Duplicate rows deleted: " & lAffectedRows, _
          "Delete duplicate SQL from table SQL", 0, 0, Null, General.bmpIcon32, True, True)) _
  Complete (iResult As Int)
 End If
 Msgbox2Async("Are you sure to delete duplicate SQL from the table RUN_SQL?", _
     "Delete duplicate SQL from table RUN_SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = -1 Then
  strSQL = "DELETE FROM RUN_SQL WHERE ROWID NOT IN(" & _
     "SELECT MAX(ROWID) FROM RUN_SQL " & _
     "GROUP BY SQL)"
  General.SQL1.ExecNonQuery(strSQL)
  lAffectedRows = GetNumberOfChanges
  wait for (cEvents.ShowMsg("Duplicate rows deleted: " & lAffectedRows, _
          "Delete duplicate SQL from table RUN_SQL", 0, 0, Null, General.bmpIcon32, True, True)) _
  Complete (iResult As Int) 
 End If
End Sub

And in the class:

B4X:
Public Sub ShowMsg(strPrompt As String, _
         strTitle As String, _
         iTitleColour As Int, _
         iPromptColour As Int, _
         csPrompt As CSBuilder, _
         bmpIcon As Bitmap, _
         bCancelable As Boolean, _
       bWait As Boolean) As ResumableSub
 
 Dim csTitle As CSBuilder
 
 'so like optional colour argument
 If iTitleColour = 0 Then
  iTitleColour = Colors.RGB(0, 0, 0)
 End If
 
 If iPromptColour = 0 Then
  iPromptColour = Colors.RGB(0, 0, 0)
 End If
 
 csTitle.Initialize.Color(iTitleColour).Append(strTitle).Pop
 
 'so csPrompt is like an optional argument, passing Null works fine
 If csPrompt.IsInitialized = False Then
  csPrompt.Initialize.Color(iPromptColour).Append(strPrompt).Pop
 End If
 
 'can pass Null for no icon
 Msgbox2Async(csPrompt, csTitle, "OK", "", "", bmpIcon, bCancelable)

 If bWait Then
  Wait For Msgbox_Result(iResult As Int)
  Return iResult
 End If
 
End Sub

I guess this is the solution you had in mind.
I was hoping I could leave the Wait For (
and _
Complete (iResult As Int)
out of the calling Sub and only have this in the class Sub. Reason for this is that ShowMsg
is called in many places in Main and also in other modules, so it would save some typing.
In any case this works fine now.

RBS
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Fyi - you can use the DialogResponse object (https://www.b4x.com/android/help/constants.html#dialogresponse) to check your result instead of using -1 to check for positive. Same thing, but just makes the code a bit more readable when you come back years later & can't remember what it was you were trying to do... :)

Eg:
B4X:
Msgbox2Async("Are you sure to delete duplicate SQL from the table SQL?", _
     "Delete duplicate SQL from table SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = DialogResponse.POSITIVE Then
...

- Colin.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Fyi - you can use the DialogResponse object (https://www.b4x.com/android/help/constants.html#dialogresponse) to check your result instead of using -1 to check for positive. Same thing, but just makes the code a bit more readable when you come back years later & can't remember what it was you were trying to do... :)

Eg:
B4X:
Msgbox2Async("Are you sure to delete duplicate SQL from the table SQL?", _
     "Delete duplicate SQL from table SQL", "Yes", "No", "",  General.bmpIcon32, False)
 Wait For Msgbox_Result(result As Int)
 If result = DialogResponse.POSITIVE Then
...

- Colin.

Yes, thanks, that makes sense.

RBS
 
Upvote 0
Top