Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
   
    Dim Thread1 As Thread
    Dim Thread2 As Thread
    Dim Lock1 As Lock
    Dim Lock2 As Lock
    Dim end1 As Int
    Dim ok As Boolean
    Dim msg As String
End Sub
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
   
    Dim btnStart As Button
    Dim btnStatus As Button
    Dim btnStop As Button
    Dim btnError As Button
   
    Dim EditText1 As EditText
    Dim EditText2 As EditText   
    Dim ProgressBar1 As ProgressBar
End Sub
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    If FirstTime Then
        Thread1.Initialise("Thread1")
        Thread2.Initialise("Thread2")
    End If
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub ThreadSub1
    end1 = 0
    Dim Count As Int
    Dim Params(1) As Object
    Do While Count < 1000
        Count = Count + 1
        Params(0) = Count
        end1 = Count
        ok = False
        Do Until ok
            ' this is because Android seems to lose the run message if the user presses back button
            ' this way no message will be ignored
            Thread1.RunOnGuiThread("Update1", Params)
            ok = Lock1.WaitFor(1000)
        Loop
    Loop
End Sub
Sub Update1(count As Int)
    EditText1.Text = count
    Lock1.Unlock
End Sub
Sub Thread1_Ended(fail As Boolean, error As String) 'An error or Exception has occurred in the Thread
    Msgbox(error, "Thread1 Ended")
End Sub
Sub ThreadSub2
    Dim Count As Int
    Dim Params(1) As Object
    Do While Count < 1000
        ' instead of locking like Thread1 we could crudely just wait for the GUI to update
        ' some messages may be lost but this may not matter in some applications
        Count = Count + 1
        Params(0) = Count
        Thread2.RunOnGuiThread("Update2", Params)
        Thread2.Sleep(10)
    Loop
End Sub
Sub Update2(count As Int)
    EditText2.Text = count
    ProgressBar1.Progress = count /10
    Lock2.Unlock
End Sub
Sub Thread2_Ended(fail As Boolean, error As String) 'An error or Exception has occurred in the Thread
    Msgbox(error, "Thread2 Ended")
End Sub
Sub btnStart_Click
    Dim args(0) As Object
    EditText1.Text = 0
    EditText2.Text = 0
    Lock1.Initialize(True)
    Lock2.Initialize(True)   
    Thread1.Name = "B4A Thread 1"
    Thread2.Name = "B4A Thread 2"
    Thread1.Start(Null, "ThreadSub1", args)       
    Thread2.Start(Null, "ThreadSub2", args)       
End Sub
Sub btnStatus_Click
    msg = "Lock1 : " & Lock1.LockState & " " & Thread1.Error & CRLF
    msg = msg & "Lock2 : " & Lock2.LockState & " " & Thread2.Error & CRLF
    Msgbox(msg, "Threading v" & NumberFormat2(Lock1.Version, 1, 1, 1, False))
End Sub
Sub btnStop_Click
    Thread1.Interrupt
    Thread2.Interrupt   
End Sub
Sub btnError_Click
    Dim Ex As ExceptionEx
    Try
        File.OpenInput("Non-existent", "file")
    Catch
        ' Catch saves the Exception to LastException which is a global variable.
        ' Because of this there is (at the moment) a 'hole' in Basic4Android Exception handling.
        ' If Exceptions are raised at the same time (admittedly a bit unlikely) on two different threads
        ' one may not see its own Exception in LastException but may see the one raised on the other thread.
        ' To mitigate this copy LastException as soon as possible to a local Exception object.
        ' The Dim for that local object is done at the start of the method to get the copy as close to Catch as possible
        Ex = LastException
        msg = Ex.StackTraceElement(0)
        Msgbox(msg, Ex.Name)
        Ex.Initialize("Oops! - No file found.")
        Ex.Throw
    End Try
End Sub