Android Question Wait For inside Threading always escape

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 :(


B4X:
Sub ThreadSub3
    'Dim Count As Int = 0
    Dim Params(1) As 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.

B4X:
Sub ThreadSub3
    'Dim Count As Int = 0
    Dim Params(1) As 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:
 

Attachments

Last edited:

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.
 

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

B4X:
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):
B4X:
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


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

 

Attachments

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.
 

Steve Kwok

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

Steve Kwok

Member
Licensed User
Do you means cutting service - svcPhptime and put it all in the activity?
B4X:
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 String) As 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
 

Steve Kwok

Member
Licensed User
Furthermore, it is simplified as:

B4X:
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 String) As 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:
Top