Thread

From Xojo Documentation

Class (inherits from Object)

Threads execute code in the background.

Events
Run UserInterfaceUpdate


Properties
DebugIdentifier StackSize ThreadState
Priority ThreadID fa-lock-32.png


Methods
AddUserInterfaceUpdate Resume Start
Pause Sleep Stop

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

You can test the state of a thread by comparing the ThreadState property to the various ThreadStates.


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

fa-exclamation-circle-32.png
Do not access any built-in property or method of a user interface control or Window from a thread's Run event or any methods called from it as platform UI frameworks (macOS, Windows and Linux) 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 not update and will be unresponsive to the user.

Typically, 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 by putting the code that updates your user interface in the UserInterfaceUpdate event and triggering it from the Run event by calling the AddUserInterfaceUpdate method inside the loop you likely have running in your Run event handler.

Keep in mind that a Thread can access your own properties and methods that are part of UI controls or Windows as long as they do not in turn access your app's user interface controls.

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.

fa-info-circle-32.png
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.
fa-info-circle-32.png
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.

See Also

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