Thread

From Xojo Documentation
Jump to: navigation, search

Class (inherits from Object)

Threads execute code in the background.

Events
Run


Properties
Priority State ReadOnlyProperty.png
StackSize ThreadID ReadOnlyProperty.png


Methods
Kill Run Suspend
Resume Sleep

Class Constants

Priority

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

Class Constant Value Description
LowestPriority 1 Lowest priority
NormalPriority 5 Normal priority (same as Main thread)
HighPriority 10 High priority

These values are totalled, then divided by the main thread and divvied out by proportion, but the main thread always has a priority of five, so using very large numbers for other threads will potentially starve the main thread. For example, if you give a second thread a priority of 500, there will be a total 505 slots in the scheduler and five of those belong to the main thread. Read more about priority below.

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 Value Description
Running 0 The thread is running normally.
Waiting 1 The thread has been blocked by a call to Signal or Enter from one of the locking mechanisms, CriticalSection, Mutex, or Semaphore.
Suspended 2 It will not execute because of a call to the Suspend method.
Sleeping 3 It has been put to sleep by a call to the Sleep method.
NotRunning 4 The thread will be in this state prior to a call to Run or after the thread has finished running.

Notes

Threads stay in scope as long as they are active, even if the variable or property referring to the thread goes out of scope.

Updating the User Interface from a Thread

Warning24.png Do not access any built-in property or method of a user interface control or Window from within a Thread as platform UI frameworks are not thread-safe. Doing so raises a ThreadAccessingUIException. See below for additional information.

Your application code normally runs in the so-called main thread which is the thread responsible for managing events in the user interface. If you have a long-running process that runs in the main thread, the user interface will appear to be locked.

You use the Thread class to run code that will not affect the state of the user interface. This also means that code that runs in these threads cannot access the user interface. Doing so raises a ThreadAccessingUIException.

Essentially, a thread is used to allow a very time-consuming process to run in the background. There may be times where you want to update the user interface with something that has been processed in the thread. The way to do this is to have the user interface request the information from the thread.

The simplest technique is to have a Timer on the Window periodically checks a property on the Thread. The Timer then uses this information to update the UI. The example below demonstrates this.

For most usage, we recommend you use the Task class included with the UIThreadingWithTask example (Examples/Desktop/UpdatingUIFromThread/UIThreadingWithTask) when you need to update UI from a Thread. The Task class is a Thread subclass that you can use in place of Thread.

Keep in mind that a Thread can access your own properties and method that are part of UI controls or Windows as long as they do not in turn access the UI.

Safely Sharing Resources Between Threads

Sometimes you may have a resource (data or a file, for example) that needs to be used by multiple threads that are all currently running. An example would be that a thread tries to open a file for writing that another thread has already opened for writing. This can cause issues and unwanted exceptions.

You can manage this by using a CriticalSection, Semaphore or Mutex to prevent multiple threads from trying to access the same shared resource.

How CPU Time is Shared Between Threads

Threads are managed by the built-in Thread Scheduler. Its task is to allocate the CPU's processing cycles among all of the application's threads. Note that because Threads are cooperative, they all share the CPU cycles of a single CPU core. Threads cannot access other CPU cores. The Priority property determines how many or how few processing cycles the Thread gets, relative to the main thread (which always has a priority of 5) and any other Threads that you have created. Use a higher value for Priority to give a thread more CPU cycles and a lower value to give it less CPU cycles.

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.

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.

You can also force context switches by calling Application.YieldToNextThread or by calling Application.SleepCurrentThread.


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.


NOTE: Code that runs in threads does not run faster (in fact such code typically runs more slowly because the CPU time is shared as described above). Putting code in a thread is a way to provide a better user experience by allows tasks to be perceived as running in the background.


Examples

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, ProgressBar, Timer and Thread object on the Window.

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.

This is the code in the PushButton Action event hander:

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

The Run event handler of the Thread is what calculates the value for the ProgressBar. ProgressValue is a property (Double) of the window.

progressValue = 0

While progressValue < 100 // if not the Maximum...
// recompute progressValue, a property of the Window
progressValue = progressValue + 1

// 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
// updates the interface with the current value that was updated by the thread
ProgressBar1.Value = progressValue
End If

See Also

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

Personal tools
Namespaces

Variants
Actions
Main
Content
Starting Out
Dig Deeper
More Help
Toolbox
About