B4A Library Threading library

This library lets you run Basic4android Subs on separate threads to the main GUI thread. It also contains a Lock (semaphore) object that can be used for resource access arbitration and thread synchronisation.

Included is also an enhanced Exception object to give more information on any Exception caught. This can also rethrow those caught Exceptions and can create new Exceptions to throw.

EDIT :- Version 1.1 posted. See post #13 for details.
 

Attachments

  • Threading1.1.zip
    19.2 KB · Views: 7,232
Last edited:

carlos7000

Well-Known Member
Licensed User
Longtime User
Hello, I simplified the example that they give but when executing it, the following message appears

WhatsApp Image 2023-08-24 at 15.46.00.jpeg


the code is the following

B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip

Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    
    Dim Thread1 As Thread

    Dim Lock1 As Lock
    Private LabelCount As Label
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    
    Thread1.Initialise("Thread1")
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Private Sub Button1_Click
    Dim args(0) As Object
    
    Lock1.Initialize(True)
    Thread1.Name = "B4A Thread 1"
    Thread1.Start(Null, "ThreadSub1", args)
End Sub

Sub ThreadSub1
    Dim Count As Int
    Dim Params(1) As Object
    Do While Count < 1000
        Count = Count + 1
        Params(0) = Count
        Dim Ok As Boolean = 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)
    LabelCount.Text = "Count " & Count
    Lock1.Unlock
End Sub

Sub Thread1_Ended(fail As Boolean, error As String) 'An error or Exception has occurred in the Thread
    MsgboxAsync(error, "Thread1 Ended")
End Sub

Attached the project
 

Attachments

  • Thread2.zip
    10.3 KB · Views: 73

stevel05

Expert
Licensed User
Longtime User
Are you trying to run it in debug mode? Try it in release mode.
 

carlos7000

Well-Known Member
Licensed User
Longtime User
Because B4XMainPage is a class instance you need to pass a reference to it in Thread.Start. See the Intellisense for Thread.Start for this and other important information.
B4X:
    Thread1.Start(Me, "ThreadSub1", args)

It worked. Since I'm going to keep messing with the threads, I'll probably keep bothering them.

thank you
 

carlos7000

Well-Known Member
Licensed User
Longtime User
Could you please explain the lines:

B4X:
Thread1.RunOnGuiThread("Update1", Params)
                Ok = Lock1.WaitFor(1000)

RunOnGuiThread clearly says Run on the Gui thread

Lock1.WaitFor is somehow used to wait for the data to display on the screen and then continue the execution of the Do While

in the function ThreadSub1 I suppose that the Lock is used to wait for the data to be displayed correctly.

Could you explain this a little better?
 

agraham

Expert
Licensed User
Longtime User
Have you read the Intellisense for Thread and Lock? I explain it all in more detail than is practical here.

In this case Lock1.WaitFor is used as a delay function as you can't use Sleep in a thread as Sleep relies on the message loop of the main thread.

Are you sure you need to use Threads at all? This library was useful in the early days of B4A but Erel has built asynchronism into most libraries that require it so the use of threads is now mainly deprecated. Without careful management of threads you may have problems with the activity lifecycle but as you are implementing a B4XPages app you should be free from this consideration.
 

carlos7000

Well-Known Member
Licensed User
Longtime User
Have you read the Intellisense for Thread and Lock? I explain it all in more detail than is practical here.

In this case Lock1.WaitFor is used as a delay function as you can't use Sleep in a thread as Sleep relies on the message loop of the main thread.

Are you sure you need to use Threads at all? This library was useful in the early days of B4A but Erel has built asynchronism into most libraries that require it so the use of threads is now mainly deprecated. Without careful management of threads you may have problems with the activity lifecycle but as you are implementing a B4XPages app you should be free from this consideration.

I'm trying to write a program that traverses a graph with at least 100 or so nodes. In some routes it has needed between 1 and 2 million cycles. The complete graph has approximately 300 nodes. Calculating the route usually takes a few seconds, but in some cases it takes several minutes. I thought about splitting the graph into subgraphs and passing each graph to a thread. I don't know if something similar could be done without threads in b4x
 

agraham

Expert
Licensed User
Longtime User
I don't know if something similar could be done without threads in b4x
Android will complain if an app doesn't return to process its message loop every few seconds to keep its user interface alive. You could achieve this by calling Sleep(0) every now and then in your route calculation Subs while running them on the main thread. Alternatively, as you are already thinking about, you could use threads. Best to try both and see which performs best. I would guess that on a device with multiple cores the thread case would perform best.

With threads you normally might need to carefully manage them as an activity is paused and resumed to avoid crashes but with B4XPages this should not be a problem as the Main activity is never paused.
 

carlos7000

Well-Known Member
Licensed User
Longtime User
Android will complain if an app doesn't return to process its message loop every few seconds to keep its user interface alive. You could achieve this by calling Sleep(0) every now and then in your route calculation Subs while running them on the main thread. Alternatively, as you are already thinking about, you could use threads. Best to try both and see which performs best. I would guess that on a device with multiple cores the thread case would perform best.

With threads you normally might need to carefully manage them as an activity is paused and resumed to avoid crashes but with B4XPages this should not be a problem as the Main activity is never paused.

I have never worked with threads, let's see how it goes.

thank you so much
 
Top