|Important||This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here.|
Thread pooling is a form of multithreading in which tasks are added to a queue and automatically started when threads are created. With thread pooling, you call the ThreadPool.QueueUserWorkItem method with a delegate for the procedure you want to run, and Visual Basic creates the thread and runs your procedure.
The following example shows how you can use thread pooling to start several tasks.
Sub DoWork() ' Queue a task System.Threading.ThreadPool.QueueUserWorkItem( _ New System.Threading.WaitCallback(AddressOf SomeLongTask)) ' Queue another task System.Threading.ThreadPool.QueueUserWorkItem( _ New System.Threading.WaitCallback(AddressOf AnotherLongTask)) End Sub Sub SomeLongTask(ByVal state As Object) ' Insert code to perform a long task. End Sub Sub AnotherLongTask(ByVal state As Object) ' Insert code to perform another long task. End Sub
Thread pooling is useful when you want to start many separate tasks without individually setting the properties of each thread. Each thread starts with a default stack size and priority. By default, up to 25 thread-pool threads can run per system processor. Additional threads in excess of the limit can be queued, but they do not start until other threads finish.
One advantage of thread pooling is that you can pass arguments in a state object to the task procedure. If the procedure you are calling requires more than one argument, you can cast a structure or an instance of a class into an Object data type.
Returning values from a thread-pool thread is not straightforward. The standard way of returning values from a function call is not allowed because Sub procedures are the only type of procedure that can be queued to a thread pool. One way you can provide parameters and return values is by wrapping the parameters, return values, and methods in a wrapper class as described in Parameters and Return Values for Multithreaded Procedures.
An easer way to provide parameters and return values is by using the optional ByVal state object variable of the QueueUserWorkItem method. If you use this variable to pass a reference to an instance of a class, the members of the instance can be modified by the thread-pool thread and used as return values.
At first it may not be obvious that you can modify an object referred to by a variable that is passed by value. You can do this because only the object reference is passed by value. When you make changes to members of the object referred to by the object reference, the changes apply to the actual class instance.
Structures cannot be used to return values inside state objects. Because structures are value types, changes that the asynchronous process makes do not change the members of the original structure. Use structures to provide parameters when return values are not needed.