Parameters and Return Values for Multithreaded Procedures
Supplying and returning values in a multithreaded applications is complicated because the constructor for the thread class must be passed a reference to a procedure that takes no arguments and returns no value. The following sections show some simple ways to supply parameters and return values from procedures on separate threads.
Supplying Parameters for Multithreaded Procedures
The best way to supply parameters for a multithreaded method call is to wrap the target method in a class and define fields for that class that will serve as parameters for the new thread. The advantage of this approach is that you can create a new instance of the class, with its own parameters, every time you want to start a new thread. For example, suppose you have a function that calculates the area of a triangle, as in the following code:
Function CalcArea(Base As Double, Height As Double) As Double CalcArea= 0.5 * Base * Height End Sub
You can write a class that wraps the
CalcArea function and creates fields to store input parameters, as follows:
Class AreaClass Public Base As Double Public Height As Double Public Area As Double Sub CalcArea() Area = 0.5 * Base * Height MsgBox("The area is: " & Area) End Sub End Class
To use the
AreaClass, you can create an
AreaClass object, and set the
Height properties as shown in the following code:
Protected Sub TestArea() Dim AreaObject As New AreaClass() Dim Thread As New System.Threading.Thread _ (AddressOf AreaObject.CalcArea) AreaObject.Base = 30 AreaObject.Height = 40 Thread.Start() End Sub
Notice that the
TestArea procedure does not check the value of the
Area field after calling the
CalcArea method. Because
CalcArea runs on a separate thread, the
Area field is not guaranteed to be set if you check it immediately after calling
Thread.Start. The next section discusses a better way to return values from multithreaded procedures.
Returning Values From Multithreaded Procedures
Returning values from procedures that run on separate threads is complicated by the fact that the procedures cannot be functions and cannot use ByRef arguments. The best way to return values is to have your multithreaded procedure call a procedure in your application, and then pass the results as arguments. To do this, raise an event when a task is done, and process the results with an event handler.
The following example returns a value by raising an event from a procedure running on a separate thread:
Class AreaClass2 Public Base As Double Public Height As Double Private Area As Double Public Event ThreadDone(ByVal Area As Double) Sub CalcArea() Area = 0.5 * Base * Height ' Calculate the area of a triangle. RaiseEvent ThreadDone(Area) ' Raise an event to return the area. End Sub End Class Dim WithEvents AreaObject2 As AreaClass2 Protected Sub TestArea2() AreaObject2 = New AreaClass2() Dim Thread As New System.Threading.Thread _ (AddressOf AreaObject2.CalcArea) AreaObject2.Base = 30 AreaObject2.Height = 40 Thread.Start() End Sub Sub AreaDoneEventHandler(ByVal Area As Double) _ Handles AreaObject2.ThreadDone MsgBox("The area is: " & Area) End Sub
You can provide parameters and return values to thread pool threads by using the optional ByVal state object variable of the QueueUserWorkItem method. Thread timer threads also support a state object for this purpose. For information on the thread pooling and thread timers, see Thread Pooling and Thread Timers.
Thread States | Thread Pooling | Thread Synchronization | Events and Event Handlers | Multithreaded Applications | Multithreading with Forms and Controls| Delegates and the AddressOf Operator | Multithreading in Components