Android Question Wait For inside Threading always escape

Discussion in 'Android Questions' started by Steve Kwok, Jul 15, 2019.

  1. Steve Kwok

    Steve Kwok Member Licensed User

    Hi, All.
    I would like to download data from internet periodically by background thread.
    With reference to:
    Threading library
    https://www.b4x.com/android/forum/threads/threading-library.6775/,
    I changed the code as follow but get freezed :(

    [​IMG]
    Code:
    Sub ThreadSub3
        
    'Dim Count As Int = 0
        Dim Params(1As Object
        
    Dim ok3 As Boolean = False
        
    Dim trying As Int = 0
        
    Dim Count As Int
        
    Do While Count < 1000
            Count = Count + 
    1
            Params(
    0) = Count
            sendPhpTimeIntent
            
    Wait For getJobResponse(map_1 As Map)
            
    StopService(svcPhpTime)
            LogColor(
    "Start time: " & map_1.Get("start"), Colors.Blue)
            LogColor(
    "End time: " & map_1.Get("end"), Colors.Blue)
            
    '******************************************
            'This not work and get freeze!!!
            Do Until ok3
                
    'Count = Count + 1
                Params(0) = Count
                
    ' this is because Android seems to lose the run message if the user presses back button
                ' this way no message will be ignored
                Thread3.RunOnGuiThread("Update3", Params)
                ok3 = Lock3.WaitFor(
    1000)
                
    If ok3 Then
                    LogColor(
    "ok3's value: " & ok3 & " with trying: " & trying, Colors.Blue)
                
    Else
                    LogColor(
    "ok3's value: " & ok3 & " with trying: " & trying, Colors.Red)
                
    End If
                trying = trying + 
    1
            
    Loop
        
    Loop
     
    End Sub
    if I skip Do Until ... Loop, it seems work.
    [​IMG]
    Code:
    Sub ThreadSub3
        
    'Dim Count As Int = 0
        Dim Params(1As Object
        
    Dim ok3 As Boolean = False
        
    Dim trying As Int = 0
        
    Dim Count As Int
        
    Do While Count < 1000
            Count = Count + 
    1
            Params(
    0) = Count
            sendPhpTimeIntent
            
    Wait For getJobResponse(map_1 As Map)
            
    StopService(svcPhpTime)
            LogColor(
    "Start time: " & map_1.Get("start"), Colors.Blue)
            LogColor(
    "End time: " & map_1.Get("end"), Colors.Blue)
            
    '*****************************************
    '        This Work!
            Thread3.RunOnGuiThread("Update3", Params)
        
    Loop
     
    End Sub
    Php Code with file name: sleepfor1sec.php:
    PHP:
    <?php
    // displaying time
    $start date('h:i:s');
    // delaying execution of the script for 5 seconds
    sleep(1);
    // displaying time again
    $end date('h:i:s');
    echo 
    "{\"start\":\"" $start "\",\"end\":\"" $end "\"}";
    ?> 
    It seems that Wait For inside Thread would escape. How can make "wait for" not escape?

    Program run in video:
     

    Attached Files:

    Last edited: Jul 15, 2019
    Wong Ka Chun and Leo Chu like this.
  2. DonManfred

    DonManfred Expert Licensed User

    Leo Chu, Peter Simpson and Erel like this.
  3. Erel

    Erel Administrator Staff Member Licensed User

    Don't use the threading library at all. This is not the correct way to program in B4A.

    OkHttpUtils2, like many other libraries, takes care of handling the slower tasks on background threads. Your code should run on the main thread.
     
    Leo Chu likes this.
  4. Steve Kwok

    Steve Kwok Member Licensed User

    Dear DonManfred and Erel,

    I try not using thread (i.e. comment Thread3) and directly access the edittext (UI) instead.

    ThreadSub3 -> NonThreadSub

    Code:
    Sub NonThreadSub
        
    Dim Count As Int   
        
    Do While Count < 10
            Count = Count + 
    1
            sendPhpTimeIntent
            
    Wait For getJobResponse(map_1 As Map)
            
    StopService(svcPhpTime)
            LogColor(
    "Start time: " & map_1.Get("start"), Colors.Blue)
            LogColor(
    "End time: " & map_1.Get("end"), Colors.Blue)
            
    'Thread3.RunOnGuiThread("Update3", Params)
            'Access UI directly
            EditText3.Text = Count
        
    Loop         
    End Sub
    Inside the service (HttpJobs):
    Code:
    Dim job As HttpJobs

    Private Sub Send   
        job.Initialize(
    "", Me)
        job.Download(myUrl)
    End Sub

    Private Sub JobDone(j As HttpJob)
        
    If j.Success Then
            
    Dim isParsedSuccess As Boolean = False
            
    Try
                isParsedSuccess = parseJson(j.GetString)
            
    Catch           
                strErrMessage = 
    "svcPhpTime.JobDone:" & LastException.Message
                LogColor(strErrMessage, 
    Colors.Red)
            
    End Try
            
    If isParsedSuccess Then
                
    If IsPaused(mySender) = False Then
                    CallSubDelayed2(mySender, 
    "getJobResponse", mapResultPair)
                
    Else
                    
    Log("JobDone")
                    
    StopService("")
                
    End If
            
    Else   
                
    If IsPaused(mySender) = False Then
                    CallSubDelayed2(mySender, 
    "getJobFailureResponse", strErrMessage)
                
    Else
                    
    Log(strErrMessage)
                    
    StopService("")
                
    End If
            
    End If       
        
    Else
            strErrMessage = j.ErrorMessage
            LogColor(
    "svcPhpTime Error: " & CRLF & strErrMessage, Colors.red)
            
    If IsPaused(mySender) = False Then
                CallSubDelayed2(mySender, 
    "getJobFailureResponse""Network Access Error!!!!!!" & CRLF & "Please check the record.")
            
    Else
                
    Log("Network Access Error!!!!!!" & CRLF & "Please check the record.")
                
    StopService("")
            
    End If
        
    End If
        j.Release
    End Sub
    [​IMG]

    It works without ANR (i.e. Android Not Response). :)

     

    Attached Files:

  5. Erel

    Erel Administrator Staff Member Licensed User

    This code is much more complicated than it should be.

    1. You need to learn how to wait for resumable subs.
    2. It will probably be simpler to send the HttpJob directly from NonThreadSub.
     
  6. Steve Kwok

    Steve Kwok Member Licensed User

    Is it better to put HttpJobs and its response (i.e. JobDone) inside service than put it in activity?
     
  7. Erel

    Erel Administrator Staff Member Licensed User

  8. Steve Kwok

    Steve Kwok Member Licensed User

    Do you means cutting service - svcPhptime and put it all in the activity?
    Code:
    Sub NonThreadSub
        
    Dim Count As Int   
        
    Do While Count < 10
            Count = Count + 
    1
            
    Dim job As HttpJob
            job.Initialize(
    "", Me)
            job.Download( 
    "http://starbuckz.125mb.com/sleepfor5sec.php")
            
    'Access UI directly
            EditText3.Text = Count
        
    Loop
    End Sub

    Private Sub JobDone(j As HttpJob)
        
    If j.Success Then
            
    Dim isParsedSuccess As Boolean = False
            
    Try
                isParsedSuccess = parseJson(j.GetString)
            
    Catch
                strErrMsg = 
    "svcPhpTime.JobDone:" & LastException.Message
                LogColor(strErrMsg, 
    Colors.Red)
            
    End Try
            
    If isParsedSuccess Then           
                
    Log("JobDone")
            
    Else           
                
    Log(strErrMsg)
            
    End If
        
    Else
            strErrMsg = j.ErrorMessage
            LogColor(
    "svcPhpTime Error: " & CRLF & strErrMsg, Colors.red)       
            
    Log("Network Access Error!!!!!!" & CRLF & "Please check the record.")       
        
    End If
        j.Release
    End Sub

    Private Sub parseJson(jstr As StringAs Boolean
        
    Dim jParser As JSONParser
        
        
    Try
            jParser.Initialize(jstr)
            mapResultPair = jParser.NextObject
            
    Return True
        
    Catch
            
    Dim strErrMessage As String = LastException.Message
            LogColor(
    "svcPhpTime.parseJson: " & CRLF & strErrMessage, Colors.Red)
            
    Return False
        
    End Try
    End Sub
     
  9. Steve Kwok

    Steve Kwok Member Licensed User

    Furthermore, it is simplified as:

    Code:
    Sub NonThreadSub
        
    Dim Count As Int  
        
    Do While Count < 10
            Count = Count + 
    1
            
    Dim job As HttpJob
            job.Initialize(
    "", Me)
            job.Download( 
    "http://starbuckz.125mb.com/sleepfor5sec.php")
            
    Wait For JobDone(j As HttpJob)
            
    If j.Success Then
                
    Dim isParsedSuccess As Boolean = False
                
    Try
                    isParsedSuccess = parseJson(j.GetString)
                    LogColor(
    "Start time: " & mapResultPair.Get("start"), Colors.Blue)
                    LogColor(
    "End time: " & mapResultPair.Get("end"), Colors.Blue)
                
    Catch
                    strErrMsg = 
    "svcPhpTime.JobDone:" & LastException.Message
                    LogColor(strErrMsg, 
    Colors.Red)
                
    End Try
                
    If isParsedSuccess Then
                    
    Log("JobDone")
                
    Else
                    
    Log(strErrMsg)
                
    End If
            
    Else
                strErrMsg = j.ErrorMessage
                LogColor(
    "svcPhpTime Error: " & CRLF & strErrMsg, Colors.red)
                
    Log("Network Access Error!!!!!!" & CRLF & "Please check the record.")
            
    End If
            j.Release
            
    'Access UI directly
            EditText3.Text = Count
        
    Loop
    End Sub

    Private Sub parseJson(jstr As StringAs Boolean
        
    Dim jParser As JSONParser   
        
    Try
            jParser.Initialize(jstr)
            mapResultPair = jParser.NextObject
            
    Return True
        
    Catch
            
    Dim strErrMessage As String = LastException.Message
            LogColor(
    "svcPhpTime.parseJson: " & CRLF & strErrMessage, Colors.Red)
            
    Return False
        
    End Try
    End Sub
     
    Last edited: Jul 15, 2019
  10. Erel

    Erel Administrator Staff Member Licensed User

    Looks better!
     
  11. Steve Kwok

    Steve Kwok Member Licensed User

    Dear Erel,
    You make my concept clear.
    Thanks a lot.:)
     
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