Press on the image to return to the main documentation page.
Written by Andrew Graham
Basic4Android applications have only one thread, the main or GUI (Graphical User Interface) thread that, not surprisingly, handles the user interface (and everything else). Using this library you can create additional threads that operate (apparently) in parallel alongside each other and the GUI thread. Threads can be useful to keep the user interface alive while performing a long sequence of computations or while waiting for something to happen.
Such threads are not allowed to manipulate GUI elements directly but this can be achieved by the Thread.RunOnGuiThread method that runs a Sub on the main GUI thread.
This library contains a Thread object that runs the Basic4Android Sub on a separate thread, a Lock object to facilite orderly use of resources by different threads and can also be used to synchronise threads and an Exception object to give more flexibility in handling exceptions than is native to Basic4Android.
Returns the cause of this Exception, or Null if there is no cause.
Constructs a new ExceptionEx with the current stack trace and the specified message.
MessageAsString [read only]
Returns the information message which was provided when this Exception was created. Returns null if no message was provided at creation time.
NameAsString [read only]
Returns the name of the class of this Exception which identifies the type of the Exception.
StackTraceAsString [read only]
Returns a string containing the entire stack trace for this Exception.
StackTraceElement (indexAsInt) AsString
Returns a string describing the stack trace element at position index in the stack trace for this Exception. Index 0 is the one at the top of the stack and identifies the method and line number in the Java source code at which this Exception was thrown.
StackTraceElementFile (indexAsInt) AsString
Returns the name of the Java source file containing the method belonging to this StackTraceElement.
StackTraceElementLine (indexAsInt) AsInt
Returns the line number in the Java source for the method belonging to this StackTraceElement. Only useful for the gurus amongst us!
StackTraceElementMethod (indexAsInt) AsString
Returns the name of the method belonging to this StackTraceElement.
StackTraceLengthAsInt [read only]
Returns the number of stack trace entries in the stack trace for this Exception.
Throws this Exception.
Returns a string containing both the name of this Exception and the message, if any, provided when it was created.
Makes a new locked Semaphore, with zero permits, or an unlocked Semaphore with one permit. A Semaphore initialised unlocked can be used to control access to a resource. To acquire a resource the sequence for a thread is Wait() - use resource - UnLock(). A Semaphore initialised locked can be used to flag events across threads. The sequence is for the waiting thread to call Wait() and the invoking thread to call Unlock().
Sets the lock on this Semaphore. Any thread now trying to wait on it will halt waiting for some other thread to unlock it.
LockStateAsBoolean [read only]
Returns the state of this Lock, True if locked, False otherwise. Note that in some situations this might become invalid as soon as it is read if another thread uses this Lock.
Frees the lock allowing one other thread waiting on it to proceed. If no threads are waiting then the next thread that tries to wait will proceed immediately setting the lock as it does.
VersionAsDouble [read only]
Returns the version number of the library.
Causes the calling thread to wait on this lock until it becomes free. If this is locked then the calling thread will halt until another thread frees it, the waiting thread will then proceed and the lock is imediately set again. If it is already unlocked then the thread does not wait but proceeds immediately setting the lock as it does so.
WaitFor (timeoutAsInt) AsBoolean
Causes the calling thread to wait on this lock until it becomes free or until the timeout expires. If the specified waiting time elapses without the lock becoming free then the value False is returned. If the time is less than or equal to zero, the method will not wait at all. If this is locked then the calling thread will halt until another thread frees it or the timeout expires. If during the wait the lock is freed then the waiting thread will proceed and and this method returns True and the lock is immediately set again. If it is already unlocked then the thread does not wait but proceeds immediately returning True and setting the lock as it does so.
This is the Thread object that actually runs a Basic4Android Sub on a separate thread. Normally Threads should be created as Process objects so they will persist as long as the application exists. This will make their behaviour easier to predict and control rather them being Activity objects which will need recreating when an activity resumes which might leave orphan threads running that could cause unexpected problems.
Ended(endedOK As Boolean, error As String) 'The thread has terminated. If endedOK is False error holds the reason for failure
Because Exceptions in a separate thread are not passed back to the main thread and can cause the application to hang any Exceptions are trapped in the Thread object Start method and the Exception message saved in the Error property and the thread Ended event raised on the main GUI thread. Reading this property gets the description of any exception caused by the thread code and is the same string that is passed to the Ended event.
Because Exceptions in a separate thread are not passed back to the main thread and can cause the application to hang any Exceptions are trapped in the Thread object Start method and the Exception object saved in the Exception property and the thread Ended event raised on the main GUI thread. Reading this property returns the saved Exception object.
Initialises the thread object with the given event name.
Posts an interrupt request to this thread. The thread is only interrupted if the thread is doing I/O or is in a wait-state (having called wait() on a LockFlag. If the thread is blocked in a join() or sleep() it will be woken up, its interrupt status will be cleared, and it will receive an InterruptedException. If the thread is blocked in an I/O operation of an InterruptibleChannel it will have its interrupt status set and receive a ClosedByInterruptException and the channel will be closed. If the thread Sub code is running freely without waiting or blocking and it knows that it might be expected to stop on an Interrupt then it should periodically check the IsInterrupted property and exit gracefully if it is True. Otherwise the recommended way of stopping a thread is for it to inspect a global variable whose value will tell it to stop or perform some other action.
IsInterruptedAsBoolean [read only]
Returns a boolean indicating whether the thread has a pending interrupt request (True) or not (False). It also has the side-effect of clearing the flag.
Join (mSecsAsInt) AsBoolean
Blocks the calling thread until the called thread finishes its execution and dies or the specified timeout expires, whichever happens first. Passing a value of zero or less blocks the calling thread until the called thread finishes its execution and dies.
MaxPriorityAsInt [read only]
The maximum priority value allowed for this thread.
MinPriorityAsInt [read only]
The minimum priority value allowed for a thread.
Sets or returns the name of the Thread. This name is displayed in DDMS while the thread is running. The default name for a thread is the event name passed to Initialise.
NormalPriorityAsInt [read only]
The normal (default) priority value assigned to threads.
Sets or returns the priority of the Thread.
RunningAsBoolean [read only]
Returns True if the thread has already been started and still runs code (hasn't died yet). Returns False either if the thread hasn't been started yet or if it has already started and run to completion and died.
Causes the specified Sub to be scheduled for execution on the main GUI thread. This mechanism is the only way a thread can access GUI items. This call returns immediately. If it is necessary for the thread to wait for the result of the GUI operation then it should wait on a Lock that will be reset by the called Sub after it haas completed the GUI operation. Sometimes it seems that if the user presses the back button, and maybe in other scenarions, then Android loses the message and the GUI thread doesn't get it and the Sub isn't run and the Lock isn't freed so it may be advisable in this case to use WaitFor with a reasonably long timeout and retry until it returns True.
Note that this method affects the caller and not this Thread object. Causes the thread to sleep for the specified number of milliseconds suspending the thread before rescheduling it for execution. The precision of the length of sleep is not guaranteed, the Thread may sleep for more or less time than requested
Starts the new thread of execution. The specified Sub will be called by the newly started thread and passed the provided parameters. Returns True if the thread was started, False if the thread is already running and a new one could not be started. Threads are always started as daemon threads which are threads that will be killed when the main application thread terminates. Because Exceptions in a separate thread are not passed back to the main thread and can cause the application to hang any uncaught Exceptions thrown in the thread Sub are trapped and saved in the threads Error property. The Thread ends when the thread Sub returns or throws an uncaught Exception. When the thread terminates, for whatever reason, the Ended event is raised. If the thread terminated normally then the Ended event endedOK parameter is True otherwise endedOK is False and the error parameter contains the reason which is the same string returned by reading the Error property. If a Sub includes a Try - Catch it can always rethrow the exception using an ExceptionEx object. The actual Exception is saved in the Exception property and can be examined by assigning it to an ExceptionEx object.
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.
... 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
VersionAsDouble [read only]
Returns the version number of the library.
Note that this method affects the caller and not this Thread object. This causes the calling thread to sleep for zero milliseconds which has the effect of suspending the thread and immediately rescheduling it for execution.