Class

Task


Warning

This item was deprecated in version 2019r2. Please use Thread as a replacement.

Description

Task is a Thread subclass that has a mechanism for allow user interface updates. Task is not part of the Xojo Framework.

Methods

Name

Parameters

Returns

Shared

AddUserInterfaceUpdate

data As Dictionary

Pause

Resume

Sleep

MilliSeconds As Integer, [WakeEarly As Boolean]

SleepCurrent

milliseconds As Integer

Start

Stop

UpdateUI

YieldToNext

Events

Name

Parameters

Returns

Run

UpdateUI

UserInterfaceUpdate

data() As Dictionary

Property descriptions


Task.Current

Current As Thread

Returns the thread that was executing at the moment this property was read.

This property is read-only.

This property is shared.

This property is Nil when accessed from the main thread.


Task.DebugIdentifier

DebugIdentifier As String

Identifer which will show up in the debugger's thread popup.


Task.Priority

Priority As Integer

Gets and sets the relative priority of the thread.

The Priority can be changed while a Thread is running.

The application's main thread has a priority of 5 and this is also the default value of any programmatically created threads. If you don't modify this value, your application will behave normally, in the sense that all the threads will share the CPU's resources equally.

Increasing the value of Priority above 5 gives that thread more processing cycles than other threads. Doubling the value of Priority will double the number of processing cycles the thread gets. A thread with a Priority of 1 will get one-fifth the processing cycles as the main thread. The range is 1 to 2^31-1, but very high values of Priority will make it difficult for other threads to run at all. The value of Priority changes the way in which threads get processing cycles only if their values are not all equal. You can use the following class constants to assign to Priority or to compare its value:

Value

Description

1

LowestPriority

5

NormalPriority

10

HighPriority

You do not need to use these constants; you can use any legal integer value instead.

This example lowers the priority of the thread prior to calling its Run method.

Thread1.Priority = Thread.LowestPriority
Thread1.Run

Task.StackSize

StackSize As Integer

The size of the stack, in bytes.

The StackSize can only be set when the thread is not running. The default stack size is 512KB on macOS and Linux and 1MB on Windows. A StackSize of zero indicates the default is used.

There is generally little reason to change this. Each stack frame only need to contain information about the parameters, local variables and return address for a method call. This does not include memory needed for objects. It would take a significant amount of local variables or parameters with method calls that are 100s of levels deep in order to exhaust the stack space.

Thread1.StackSize = 96000

Task.ThreadID

ThreadID As Integer

ID of the thread, assigned at runtime.

This property is read-only.

Note: ThreadID will be non-zero only when the Thread is running.

This example reports the ThreadID only if the thread is running.

If LongProcessThread1.State <> Thread.NotRunning Then
  MessageBox(LongProcessThread1.ThreadID.ToString)
Else
  MessageBox("The thread is not running!")
End If

Task.ThreadState

ThreadState As Thread.ThreadStates

Indicates the state of the thread.

This property is read-only.

A thread can be in one of five states. See Thread for details.

This window method checks the State of the thread and displays a message in a TextField on the form. The parameter is:

State As Thread.ThreadStates
Select Case State
Case Thread.ThreadStates.Running
  TextField1.Text = "Running"
Case Thread.ThreadStates.Waiting
  TextField1.Text = "Waiting"
Case Thread.ThreadStates.Sleeping
  TextField1.Text = "Sleeping"
Case Thread.ThreadStates.Paused
  TextField1.Text = "Paused"
Case Thread.ThreadStates.NotRunning
  TextField1.Text = "Not Running"
End Select

Method descriptions


Task.AddUserInterfaceUpdate

AddUserInterfaceUpdate(data As Dictionary)

Triggers the UserInterfaceUpdate event so you can update your user interface from the thread.


Task.Pause

Pause

Puts the thread in a paused state. Every call to Pause must be matched by a call to Resume.

The thread will not be allocated any processing cycles, regardless of its assigned Priority. It is “asleep.” To wake it up, call the Resume method. If the thread is executing when you call Pause, it will immediately cause a context switch.

This example calls Pause, followed by a call to Resume after other code has executed.

LongProcessThread1.Pause
' do something else here...
LongProcessThread1.Resume

Task.Resume

Resume

Wakes up a thread that was paused because of a call to Thread or is sleeping because of a call to Thread. Every call to Pause must be matched by a call to Resume.

When you call Resume, the thread reacquires its ability to receive processing cycles according to its value of Priority. Calling Resume will not cause a context switch to take place, that is, a switch to the next thread in the queue.

LongProcessThread1.Resume

Task.Sleep

Sleep(MilliSeconds As Integer, [WakeEarly As Boolean])

Puts the thread to sleep for the specified amount of time.

By default, WakeEarly is False. If it is not set to True, the thread will be put to sleep for the full amount of time specified by MilliSeconds. If you set WakeEarly to True, the thread can be resumed early. It will wake up early if there are no other threads able to execute.

LongProcessThread1.Sleep(300, True)

Task.SleepCurrent

SleepCurrent(milliseconds As Integer)

Sleeps the currently executing thread for the specified number of milliseconds.

This method is shared.

If the currently executing thread is the main thread, it will sleep like any other thread would.


Task.Start

Start

Starts the thread's Run event handler.


Task.Stop

Stop

Stops the specified thread.

Internally, this method will cause your thread's stack to unwind, destructors for local objects to be called, and so forth. It's a graceful exit which can cause code to execute. It may also cause context switches.

Note

A thread should not stop itself. Instead, just return from the Run event handler to allow the thread to end.

This example, which is in the Action event of a button, stops the thread.

LongProcessThread1.stop

Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.


Task.UpdateUI

UpdateUI

Calls the UpdateUI event handler where you can update the user interface. Pass in necessary arguments as a Pair.

In the Run method of the Task subclass, call the UpdateUI method to supply arguments that will be sent to the UpdateUI event handler where you can directly update the user interface.

This code updates a ProgressBar passing in the value to use as a Pair:

Dim progressValue As Integer

While progressValue < 100
  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

  ' Call UpdateUI with any parameters you need. This calls the UpdateUI event handler
  ' where you can directly access any UI controls on the Window.

  ' This specifies simple parameters using a Pair
  ' You can also pass values using a Dictionary
  Me.UpdateUI("UIProgress":progressValue)

Wend

This code updates a ProgressBar passing in the value to use as a Dictionary:

Dim progressValue As Integer

While progressValue < 100
  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

  ' Call UpdateUI with any parameters you need. This calls the UpdateUI event handler
  ' where you can directly access any UI controls on the Window.
  Dim d As New Dictionary
  d.Value("UIProgress") = progressValue
  Me.UpdateUI(d)

Wend

Task.YieldToNext

YieldToNext

Causes the current thread to yield its time to the next thread.

This method is shared.

This causes the Thread Scheduler to yield the currently executing thread's processing time to the next Thread in the queue that is awaiting processing cycles. It is possible for the next Thread to be the currently executing Thread.

Event descriptions


Task.Run

Run

The Run method has been called. The threaded code is placed in this event handler. Methods called from here also run in the thread.

MacOS apps cannot access the user interface from within a thread. Doing so raises a ThreadAccessingUIException. Instead, use the Thread method in conjunction with the Thread event. See the Thread event for an example.


Task.UpdateUI

UpdateUI

In this event handler, you can do user interface updates. This is called by calling the UpdateUI method.

You can supply a variety of values (as a Dictionary that you can use to determine what to update and how to update it.

This code checks for passed value to use to update a ProgressBar on the Window:

If args.HasKey("UIProgress") Then
  UIProgress.Value = args.Value("UIProgress").IntegerValue
End If

Task.UserInterfaceUpdate

UserInterfaceUpdate(data() As Dictionary)

Used to update your app's user interface.

Apps cannot access the user interface from within the Run event of a thread. Doing so raises a ThreadAccessingUIException. Instead, use the UserInterfaceUpdate event to update your user interface. It can be triggered by calling the AddUserInterfaceUpdate method from within the Run event.

Each call to AddUserInterfaceUpdate in the Run event, adds the values passed to an array that is then passed to the UserInterfaceUpdate event (the data() parameter above). This allows you to process all of the calls to AddUserInterfaceUpdate or just the most recent one. For example, if your thread was reading a series of files and you wished to add the name of each file read to a ListBox, you'd want to read each row of the data() array passed to this event. However, if you instead were only displaying a ProgressBar and wanted to show how far you'd gotten through reading all the files, it would be more efficient to read the last item of the data() array passed to this event and then update your ProgressBar control rather than iterate through all of the items in the data() array.

This code (in the UserInterfaceUpdate event) updates a ProgressBar (called UIProgress) on a Window:

For Each update As Dictionary In data
  If update.HasKey("UIProgress") Then
     UIProgress.Value = update.Value("UIProgress").IntegerValue
  End If
Next

The Data parameter is an array of Dictionaries containing information supplied by the AddUserInterfaceUpdate method that can be used to update the UI.

The Run method contains the code that runs in the thread and calls AddUserInterfaceUpdate with any necessary information:

Var progressValue As Integer

While progressValue < 100
  progressValue = progressValue + 1

  //Your processing code goes here. For the sake of this example
  //we've added a dummy loop below so you can see the progress bar update.

  ' Do nothing for 1/4 second
  Var waitUntil As Integer = System.Ticks + 15
  While System.Ticks < waitUntil
  Wend

  ' Call AddUserInterfaceUpdate with any parameters you need. This calls the UserInterfaceUpdate event handler
  ' where you can directly access any UI controls on the Window.

  ' This specifies simple parameters using a Pair
  ' You can also pass values using a Dictionary
  Me.AddUserInterfaceUpdate("UIProgress":progressValue)

Wend

Notes

Task is not part of the Xojo framework, but because UI access from a thread raises a ThreadAccessingUIException, it is important enough to warrant its own API entry.

If you instantiate a Task in a local variable, keep in mind that the Task instance only remains available as long as both the variable is in scope and the thread is running. If the variable goes out of scope then it is possible the thread will complete but not be able to process its UpdateUI event because it is no longer available. To avoid this you should instead create your instance as a property so that it remains available longer or add a Sleep call of sufficient time to the end of the thread so that the UpdateUI event has enough time to run.

Sample code

To use Task, add both TaskEvent and Task to your project and then drag Task onto a Layout Editor.

In the UpdateUI event handler, you add put the code that accessing the UI. This code updates a ProgressBar (called UIProgress) on a Window:

If args.HasKey("UIProgress") Then
  UIProgress.Value = args.Value("UIProgress").IntegerValue
End If

The args parameter is a Dictionary containing information supplied by the UpdateUI method that can be used to update the UI.

The Run method contains the code that runs in the thread and calls UpdateUI with any necessary information:

Dim progressValue As Integer

While progressValue < 100
  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

  ' Call UpdateUI with any parameters you need. This calls the UpdateUI event handler
  ' where you can directly access any UI controls on the Window.

  ' This specifies simple parameters using a Pair
  ' You can also pass values using a Dictionary
  Me.UpdateUI("UIProgress":progressValue)

Wend

Compatibility

All project types on all supported operating systems.

See also

Thread parent class; Thread