iOS Question Run a Sub in background thread without blocking the UI (Asynchronous)

stephane..blusson

Member
Licensed User
Hello everyone.
Maybe someone can help with advice. I am developing a chat. I want that when the application starts, a request is sent and received a JSON file with all messages in order to update all chats. But while this function is being executed, the interface stops responding to clicks. I found this class


but it could not help me (the interface is still blocked)

I initialize the class when the application starts
B4X:
Dim myBGTask As BackgroundTask
myBGTask.Initialize("Task", Me, Array())

then I create two methods

B4X:
Sub Task

    Log("******************************Task******************************")
      
    Dim job1 As HttpJob
    job1.Initialize("UpdateAllMessages", Me)
    'Send a GET request
    Try
     
        Dim mmap As Map
        mmap.Initialize
        mmap.Put("Email", encode(mailfromdb))
        mmap.Put("Password", encode(passwordfromdb))
          
        job1.PostMultipart(rdcLingGetChat, mmap, Null)
      
    Catch
        job1.ErrorMessage = "Error"
    End Try
      
    Wait For (job1) JobDone(job1 As HttpJob)
  
    If job1.Success Then
      
        If job1.JobName = "UpdateAllMessages" Then
            Log("GetChatJSON")
            Dim res As String
            res = job1.GetString
            Log($"Result: ->${res}<-"$)
            Log("Back from Job:" & job1.JobName )
         
            Dim parser As JSONParser
          
            parser.Initialize(res)
          
            Dim rootGetChatJSON As List = parser.NextArray
            For Each colroot As Map In rootGetChatJSON
                Dim user_id As String = colroot.Get("user_id")
                Dim FirstName As String = colroot.Get("FirstName")
                Dim text As String = colroot.Get("text")
                Dim time As String = colroot.Get("time")
  
                'some sql logic

            Next
        End If
  
    End If
    job1.Release

End Sub

Sub Task_Done
    Log("End Task")
End Sub

If you believe the logs, then Sub Task_Done is called before sub Task completes its work.

Testing in release mode
 

OliverA

Expert
Licensed User
Longtime User
This may be pure conjecture:

I do not think that the downloading of your JSON data is causing the UI to block, since HttpJob is set up to be non-blocking. Most likely it is the processing of the JSON data (if there is a lot) that is blocking the UI. As to Task_Done being called before sub Task completes, this may be normal, since you are using Wait For within the Task. As soon as Wait For is executed, it exits the underlying thread and Task may actually be done for processing purposes. Most likely, you should avoid using Wait For and Sleep within this background task.

Now what?

You can try executing the HttpJob outside the Task and once you receive the JSON data, use the Task to process the JSON data. Something like

Starting code:
B4X:
Dim job1 As HttpJob
job1.Initialize("UpdateAllMessages", Me)
'Send a GET request
Try
 
    Dim mmap As Map
    mmap.Initialize
    mmap.Put("Email", encode(mailfromdb))
    mmap.Put("Password", encode(passwordfromdb))
      
    job1.PostMultipart(rdcLingGetChat, mmap, Null)
    Wait For (job1) JobDone(job1 As HttpJob)

    If job1.Success Then
      
        If job1.JobName = "UpdateAllMessages" Then
            Log("GetChatJSON")
            Dim res As String
            res = job1.GetString
            Log($"Result: ->${res}<-"$)
            Log("Back from Job:" & job1.JobName )
         
            Dim myBGTask As BackgroundTask
            myBGTask.Initialize("Task", Me, Array(res))
        End If
    Else
        ' I'm just doing this for consistency (see Catch block)
        job1.ErrorMessage = "Error"
    End If
Catch
    job1.ErrorMessage = "Error"
End Try
job1.Release

Thread code:
B4X:
Sub Task(res As String)

    Log("******************************Task******************************")
      
      
    Dim parser As JSONParser
  
    parser.Initialize(res)
  
    Dim rootGetChatJSON As List = parser.NextArray
    For Each colroot As Map In rootGetChatJSON
        Dim user_id As String = colroot.Get("user_id")
        Dim FirstName As String = colroot.Get("FirstName")
        Dim text As String = colroot.Get("text")
        Dim time As String = colroot.Get("time")

        'some sql logic
        '****************************
        'IMPORTANT!!!!!!!!!!!!!!!
        'Do NOT use ASYNC DB methods, else you will exit the thread prematurely.
        'Since this is being executed in a separate thread, using non-async methods here should not block the UI
        'If you are trying to update the UI, you may have an issue, since you should not do it here (?)
        'You then need to have a mechanism to get the data back to the main thread (CallSubDelayed? Global variable?)
        '*****************************
    Next


End Sub

Sub Task_Done
    Log("End Task")
End Sub
 
Upvote 0

stephane..blusson

Member
Licensed User
Thanks for the advice, your solution works!
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…