A Session-aware thread for use in web apps.







data As Dictionary




MilliSeconds As Integer, [WakeEarly As Boolean = False]


milliseconds As Integer










data() As Dictionary

Property descriptions


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.


DebugIdentifier As String

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


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:









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


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


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("The thread is not running!")
End If


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


AddUserInterfaceUpdate(data As Dictionary)

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



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.

// do something else here...



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.



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)


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.



Starts the thread's Run event handler.



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.


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.




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



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.


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

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

  // 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



Use of a WebThread prevents you from having to use WebSessionContext.

Allow the thread to go out of scope in order for the web framework to properly manage it. If you keep the thread alive (by having an infinite loop in its Run event handler), your sessions may not quit which could result in memory leaks.

Remember, threads stay in scope as long as they are active (running, sleeping, etc.)


The main reason to use a WebThread is that its session is retained. That means that if you do anything that would require manipulating the session, the framework can accurately figure out which session it belongs to. If you're doing something that is not session sensitive, you could use a regular Thread.


Web projects on all supported operating systems.

See also

Thread parent class; Session, Thread, WebSession, WebSessionContext