B4A Library Threading library

agraham

Expert
Licensed User
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

Last edited:

sdaly

New Member
Licensed User
Examples

Hi

Do you have any examples for threading? I'm looking to start a thread to process files and update a progress bar from this thread in the gui....
 

agraham

Expert
Licensed User
There's a demo in the archive. Threading in Android can be tricky because of activity lifecycle considerations. Have you considered the non-modal ProgressDialog in Basic4ppc which will let you do your stuff on the main thread or using a ProgressBar and DoEvents to keep it updated?
 

sdaly

New Member
Licensed User
Excelllent!

Thanks, got the new thread working....

Progress bar still doesn't update until the end of processing. I'm using as below...

pbval = pbval + 1
Dim Params(1) As Object
Params(0) = pbval
th.RunOnGuiThread("updatePb", Params)
th.Sleep(10)
 

agraham

Expert
Licensed User
I can't see anything from that fragment. This works fine for me.
B4X:
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
 

spillermarco

Member
Licensed User
Thread1.RunOnGuiThread .....

Hello, I use this library to read some data from a network device view.
the problem is that sometimes, in the opening application, the program stops saying "application terminated unexpectedly .." .
If the program starts successfully continued without stopping.
I discovered that an error is generated:

Thread1.RunOnGuiThread ("Update1", Params)

if I take off this command, the program no longer exits.

I did all the tests possible, I also recalled a sub empty, passing one parameter fixed, it should be equally in error.


By removing the filters from the log window that read:

threadid = 1: thread exiting with Uncaught exception (group = 0x40015560)

How can I do to see what went wrong?

Thanks in advance

greetings
 

corwin42

Expert
Licensed User
I tried to create a new thread in a class but it doesn't seem to work.

It seems that the thread sub gets never called and the Ended event is raised with endedOK = false imediately.

Am I doing something wrong? Attached is a small example which shows the problem.
 

Attachments

Last edited:

agraham

Expert
Licensed User
Your posted code doesn't compile without changes. Note that a Thread traps and saves any exception. You can see where it occurred with
B4X:
Dim e As ExceptionEx
e = t.Exception
Log(e.StackTrace)
In this case Thread expects to invoke a static Java method (Sub) as all Subs in Basic4android modules so far have been static. However Subs in a class are normal instance methods and so the invoke fails because no Class instance is passed to the method invocation - hence the mention of "null" in the logged error message.

I am very rusty on Android and Java but can't immediately think of an elegant way to use both static and instance methods as the Runnable for a thread. I'll think about it. Perhaps Erel might have an idea.
 

corwin42

Expert
Licensed User
Your posted code doesn't compile without changes.
Sorry, I noticed this and uploaded the correct version 5 minutes after the first one. You are just too fast. :)

In this case Thread expects to invoke a static Java method (Sub) as all Subs in Basic4android modules so far have been static. However Subs in a class are normal instance methods and so the invoke fails because no Class instance is passed to the method invocation - hence the mention of "null" in the logged error message.

I am very rusty on Android and Java but can't immediately think of an elegant way to use both static and instance methods as the Runnable for a thread. I'll think about it. Perhaps Erel might have an idea.
Ok, thank you for explaining it. Hopefully you or Erel will find a solution for it.
 

agraham

Expert
Licensed User
I've got it working by passing the class instance to Start using the new Me parameter available in version 2.0. This will also work for Subs in Activities and Services.
B4X:
   t.Start("GetAsyncDataThreadSub", Me, Array As Object(pId, pMap))
However there is a somewhat non-obvious Java typing issue to do with wrapping (or not) underlying Java objects that I need to discuss with Erel and try to clarify in the XML help.
 

JakeBullet70

Well-Known Member
Licensed User
I have been following this thread as I have a need for threads in classes.

B4X:
 t.Start("GetAsyncDataThreadSub", Me, Array As Object(pId, pMap))
This code wont compile as I get an error saying 'Too many parameters'

Ideas anybody?
 

agraham

Expert
Licensed User
Version 1.1 now posted adds a parameter to Start (a breaking change I'm afraid) to enable Class instance methods to be used as Thread Subs. The additional help for Start is posted below

For a Sub declared in a Class an object instance is required on which to invoke the thread Sub.
This can be Me if Start is called within a class or a reference to the class instance if Start
is called outside the Class.

For Subs declared in Activities and Services, which are actually static methods, an instance
is not required and null can be passed.

Note that the arguments are passed to the Sub as an Object array. This has an effect on how the
Basic4android compiler treats any object that derives from AbsObjectWrapper. When passed as an
Object the compiler unwraps the object and passes the underlying wrapped object. For this reason
the called Sub should expect the unwrapped object type and not the wrapper type by declaring the
parameter as type Object. To access the passed object assign it to a variable of the correct wrapper
type. A simple but somewhat contrived example is shown below.
B4X:
       ...
       Dim MyMap as Map
       MyMap.Initialize
      Thread1.Start(Me, "AsyncSetMap", Array As Object(myMap))
       ...
    
   Private Sub AsyncSetMap(MapObj As Object)
       Dim Map1 As Map
       Map1 = MapObj
       'Add some Data to the map
      Map1.Put("A Key", "Some Data")
   End Sub
 

JakeBullet70

Well-Known Member
Licensed User
Sorry, I misunderstood.

Thanks for the update!!!!!!!
 

tcgoh

Active Member
Licensed User
Hi,
I'm trying to use your Thread Libraries to show a progressbar when the code below is converting a large data.text file to SQL.

Its takes about 2mins to convert the 2-3 mb file. Is it possible to show a progressbar or dialog during this 2mins?
B4X:
Sub button1_click
   convert
end sub

Sub convert
   
   SQL1.ExecNonQuery("CREATE TABLE CREW (s1 TEXT , s2 TEXT, s3 TEXT, s4 TEXT, s5 TEXT, s6 TEXT, s7 TEXT, s8 TEXT, s9 TEXT, s10 TEXT )") 
   
      Dim line3 As String
         Dim i As Int

      reader.Initialize(File.OpenInput(DBFilePath,FileName))        
      
      i=0
      line3 = reader.ReadLine
      Do While line3 <> Null 
      Dim CC() As String  'CC is column content
      CC = Regex.Split(",", line3)
            
      SQL1.ExecNonQuery2("INSERT INTO " & DBTableName & " VALUES (?,?,?,?,?,?,?,?,?,?)", Array As  Object (CC(0), CC(1), CC(2), CC(3),CC(4), CC(5), CC(6), CC(7),CC(8),CC(9)))
          
       i = i + 1
                line3 = reader.ReadLine
      Loop
      
        Msgbox(i & " Records in text file were imported to ".ToUpperCase & DBTableName, "T E X T  F I L E")
   
End Sub
Thanks and regards
 

Mahares

Well Known Member
Licensed User
Perhaps, As another solution, according to Erel, you can improve the import performance of the text file into the table dramatically if you properly use begin and end transaction. I have not taken full advantage of them because my files are small. Please try and let us know how much time you save. For more details see the following post: http://www.basic4ppc.com/forum/basi...placement-transaction-keywords.html#post94614. See below code where to place them:
B4X:
SQL1.BeginTransaction
Try
    'do all the SQL statements here.
    'loop should start and end here.

    SQL1.TransactionSuccessful
Catch
    Log(LastException.Message) 'no changes will be made
End Try
SQL1.EndTransaction
 

tcgoh

Active Member
Licensed User
Thanks Mahares for coming to my rescues again.

Yes I'm now using the SQL1.BeginTransaction , endTransaction and it cuts down the time taken from 100sec to only 15sec for about 38k of records.

I've also used the

If j mod 1000 = 0 then DoEvents

to show a progressdialogshow in between. Works nicely.

Now my next question, how do I show something like Doevents for

B4X:
Do While line <> Null
      
      list2.Add(line)
      listview1.AddSingleLine(line)
         
      line=Reader1.ReadLine
      
      
      Loop
Thanks and regards
 
Top