B4J Question Updating a TextArea while running a long computation

Alessandro71

Well-Known Member
Licensed User
Longtime User
I have a TextArea view that I'm using to show progress log from a long running sub (several minutes)
Here is the code I use every 1000 results (about a second of running time) to update the TextArea with the content of a text buffer
B4X:
    TextArea1.Text = Logger.GetBuffer
    TextArea1.SetSelection(TextArea1.Text.Length, TextArea1.Text.Length)
    Sleep(0)
What really happens is that the TextArea is only updated at the end of the long running sub (and also is not scrolled to the bottom, but it stays at the top)
 
Solution
1. Make sure to test it in release mode.
2. Add:
B4X:
 If (linenumber Mod 1000) = 0 Then
          WriteLog("processing line " & linenumber)
          Sleep(0)
 End If

Alessandro71

Well-Known Member
Licensed User
Longtime User
Can't post the full code, but the structure is the following

B4X:
Private Sub WriteLog(line As String)
    Logger.WriteDebugLog("MAIN: " & line)
    
    If (TextArea1.IsInitialized) Then
        UpdateTextArea
    End If
End Sub

Private Sub UpdateTextArea
    TextArea1.Text = Logger.GetBuffer
    TextArea1.SetSelection(TextArea1.Text.Length, TextArea1.Text.Length)
    Sleep(0)
End Sub

Private Sub SplitLongLog
    Dim dir As String = Preferences.GetString(Preferences.OPT_DIR)
    Dim filename As String = Preferences.GetString(Preferences.OPT_FILENAME)
    Dim linenumber As Int = 0

    WriteLog($"Split ${dir}\${filename}"$)
    
    Private inTextFile As TextReader
    
    Try
        inTextFile.Initialize(File.OpenInput(dir, filename))
    
        Dim line As String = ""
        Do While line <> Null
            line = inTextFile.ReadLine
            
            If (line <> Null) Then
                linenumber = linenumber + 1
                If (linenumber Mod 1000) = 0 Then
                    WriteLog("processing line " & linenumber)
                End If
                
                If Regex.IsMatch(pattern, line) Then
                    'process the line
                    'time consuming
                End If
            End If
        Loop
    Catch
        Log(LastException)
    End Try

    If (inTextFile.IsInitialized) Then
        inTextFile.Close
    End If
End Sub
 
Upvote 0

Alessandro71

Well-Known Member
Licensed User
Longtime User
1. Make sure to test it in release mode.
2. Add:
B4X:
 If (linenumber Mod 1000) = 0 Then
          WriteLog("processing line " & linenumber)
          Sleep(0)
 End If
as much as I'm happy to confirm that this fixed the issue, I'm puzzled to understand the reason why, since Sleep(0) is also contained in UpdateTextArea, which is called by WriteLog itself...
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can mark my answer as the solution.
The Sleep(0) inside UpdateTextArea has no effect.
Remember the #1 rule of resumable subs: from the calling sub perspective, a call to Sleep or Wait For is equivalent to Return.
The only way for that Sleep call to have an effect is if you make the sub return ResumableSub and call it with Wait For. It is better to call Sleep directly.
 
Upvote 0
Top