Thread

From Real Software Documentation

Jump to: navigation, search
Class (inherits from Object)

Threads execute code in the background.


Events
Run


Properties
Priority State
StackSize ThreadID


Methods
Kill Sleep
Resume Suspend
Run


Class Constants

Priority

The following class constants can be used to set the priority of the thread with the Priority property.

Class Constant Description
LowestPriority Lowest priority
NormalPriority Normal priority
HighPriority High priority


State

The following class constants can be used to test the state the thread is in by examining the value in the State property.

Class Constant Description
Running The thread is running normally.
Waiting The thread has been blocked by a call to Signal or Enter from one of the locking mechanisms, CriticalSection, Mutex, or Semaphore.
Suspended It will not execute because of a call to the Suspend method.
Sleeping It has been put to sleep by a call to the Sleep method.
NotRunning The thread will be in this state prior to a call to Run or after the thread has finished running.


Notes

The Main Thread

A Real Studio application runs in the so-called main thread which is the only one managing events from the outside and the graphical user interface (UI). However, this thread is not accessible via methods of the Thread class; it is managed internally. All other threads are accessible and share execution time among each other and the main thread.


The Thread Class

Thread class objects are used to execute code that needs to run independently of the user interface. The Thread Scheduler allocates processing cycles between the main thread and any threads you create via this class.

For example, if you were drawing a complex image that takes several minutes to render, this code could be executed in a thread so that the user could continue using the user interface without having to wait for the rendering to finish.

A thread can be used to allow a very time-consuming loop to run in the background. Since unthreaded loops take over the interface, preventing the user from making menu selections or interacting with a window's controls, this is a good way to allow the user to continue working with the application while a lengthy process is taking place.


NOTE: Manipulating the UI from within a thread is not recommended and in fact is prohibited in newer versions as it can cause serious issues: application hangup, crashes... There are better and safer ways to achieve such goal.


Threads can yield time to other threads and other applications each time they execute a looping construct such as For, While, and Do. However, a thread does not necessarily yield time at every loop boundary even though it has an opportunity to do so. A thread actually yields to another thread when the Thread Scheduler decides that its timeslice has expired. Context switches are expensive, so the Thread Scheduler always tries to avoid them.

To create a thread, create a new class and make Thread its super class. Add the new class to the Project. Put the code you wish to execute in the thread's Run event handler. To execute the thread, simply create a new instance of this object and call its Run method. You can do this by adding the instance of the Thread class to a window, as shown in the example, or instantiate it in the usual way.


Safely Sharing Resources Between Threads

As threads are running simultaneously, there can be problems if 2 or more threads are using the same data. For example, if several threads may need to access the same file, you can use a CriticalSection to be sure that two or more threads are not trying to access the same file simultaneously.

See the Semaphore, CriticalSection, and Mutex classes to see how to manage access to shared resources among multiple threads


How CPU Time is Shared Between Threads?

Threads are managed by Real Studio’s Thread Scheduler. Its task is to allocate the CPU’s processing cycles among all of the application’s threads. The Priority property determines how many or how few processing cycles the thread gets, relative to the main thread and any other threads that you have created.


Threads run in the background, but are temporarily blocked by certain user actions:

  • While the mouse button is held down,
  • While a window is being dragged,
  • While a menu in the menu bar is pulled down,
  • While the mouse button is pressed on a control in a window (not true of Windows)

When the Thread Scheduler decides to stop execution of the current thread and allow another thread to run, it is called a context switch. The amount of time a thread runs is called the time slice for the thread.


NOTE: Using the DoEvents method of the Application class from a multithreaded application is not supported and will most likely generate extremely hard to track down errors and crashes in your application. See DoEvents for more information.


Examples

To set up this example, first add a new class to the Project called LongProcessThread and set its Super class to Thread. In the Run event, place the following code:

Dim i as Integer
Dim s as String
Const c = 186000
Const bigNum = 100000000

For i = 1 to bigNum
If i / 1000 = i \ 1000 then
//do something really tedious here...anything you want
s = Str(i/c*c*c) + " for " + Str(bigNum)
//just try to update the interface
Window1.ListBox1.AddRow s //add a row to the ListBox
End if
Next
MsgBox "Finished"


Add an instance of the LongProcessThread class to the default window, Window1. Add a ListBox, ListBox1, to the default window and a PushButton to the window with the following Action event handler:

LongProcessThread1.Run


This event handler does the calculations as a new thread. To see how the user-created thread makes a difference, create a second PushButton in the window and use the code in the Thread's Run event as the PushButton's Action event. When this button is clicked, Real Studio will do the same calculations, but in the main thread rather than in the thread you created.

When you do the calculation in its own thread, you will see that Real Studio is able to update the ListBox while the calculation is in progress and allows the user to manipulate interface items, such as scroll the ListBox and choose menu items. However, when you do the calculation inside the main thread, the interface is locked up until the calculation is finished.


Updating the Interface Using a Thread

The following example illustrates how to update an interface using a Timer and a Thread. The computation is done in the Thread but the interface is updated via the Timer in the main thread.

The user interface has a PushButton and a ProgressBar. A Timer and a Thread object are on the Window (see the following illustration).

The interface for the Update UI example.

The Action event of the PushButton gives the ProgressBar an ititial value and sets the mode of the Timer to Multiple. The Timer periodically checks on the status of the ProgressBar.

ProgressBar1.Value = 0
Timer1.Mode = Timer.ModeMultiple //periodically check ProgressBar and update the interface
Thread1.Run

The Run method of the Thread is what maintains the ProgressBar. ProgressValue is a property (Double) of the window.

progressValue = 0

while progressValue < 100 //if not the Maximum...
progressValue = progressValue + 1 //recompute progressValue

// do nothing for 1/4 second or so so folks can see the actual progress
dim waitUntil as integer = ticks + 15
while ticks < waitUntil
wend

wend

The Timer periodically checks the state of the ProgressBar. If it has not reached its maximum value, it updates it with the computed value.

if ProgressBar1.value >= ProgressBar1.Maximum then //tests the ProgressBar value
ProgressBar1.value = ProgressBar1.Maximum
me.mode = timer.ModeOff //turns off the checking/updating
else //if not maximum
ProgressBar1.value = progressValue //updates the interface with the current value
end if


See Also

Application, DoEvents, CriticalSection, Mutex, Semaphore, Timer, WebTimer classes; #Pragma directives; ThreadAlreadyRunningException, ThreadEndException.

Personal tools