Developers have always asked Microsoft to add more multithreading functions for VB, as does VB. NET. VB6 supports the establishment of multi-threaded EXE, DLL and OCX. However, the use of multithreading may be inaccurate. Therefore, VB6 only supports units that run multiple single threads. A unit is actually the space for code execution, and the boundary of the unit limits the code to access things other than any unit.
VB. NET is different. It supports the creation of free-threaded applications. This means that multiple threads can access the same set of shared data. The following sections of this article will discuss some basic points of multithreading.
Problem
Although VB6 supports multiple single-threaded units, it does not support a free-threaded model, that is, it does not allow many threads to use the same set of data. In many cases, you need to create a new thread for background processing to improve application availability. Otherwise, A long process can slow the response of the program. For example, if you press a Cancel button on the table, you haven't responded for a long time.
Solution
Because VB. NET uses the Common Language Runtime (CLR), it has many new features, one of which is an application that can create free threads.
Thread used
In VB. NET, it is very easy to use threads. We will discuss the details later. Now we first create a simple table, which uses a new thread to run a background processing. The first thing to do is to create a background task running on the new thread. The following code executes a fairly long running process-an infinite loop:
Private Sub BackgroundProcess ()
Dim I As Integer = 1
Do While True
ListBox1.Items. Add ("Iterations:" + I)
I + = 1
Loop
End Sub
This code loops infinitely, and adds a project to a list box on the table during each execution. If you are not familiar with VB. NET, you will find some differences between this code and VB6:
. Assign a value when declaring the variable Dim I As Integer = 1
. Replace I = I + 1 with the + = Operator I + = 1.
. The Call keyword is not used.
Once we have a job to process, we need to allocate this code to a thread for processing and start it. For this reason, we need to use a Thread object, which is part of the System. Threading namespace in the. NET architecture class. When instantiating a new Thread class, we will transmit a reference to the code block executed by the Thread class constructor to it. The following code creates a new thread object and transmits a reference of BackgroundProcess to it:
Dim t As Thread
T = New Thread (AddressOf Me. BackgroundProcess)
T. Start ()
The AddressOf operator creates a delegate object to the BackgroundProcess method. In VB. NET, a delegate is a type-safe, Object-Oriented function pointer. After instantiating this thread, you can call the Start () method of the thread to Start code execution.
Control thread
After the thread starts, you can control its status through a method of the thread object. You can call the Thread. Sleep method to pause the execution of a Thread. This method can receive an integer value to determine the Thread Sleep time. Taking the previous example as an example, if you want to slow down the increase of the list project, you can put a sleep method call in it:
Private Sub BackgroundProcess ()
Dim I As Integer = 1
Do While True
ListBox1.Items. Add ("Iterations:" + I)
I + = 1
Thread. CurrentThread. Sleep (2000)
Loop
End Sub
CurrentThread is a public static attribute value that allows you to get a reference of the current running thread.
You can also call Thread. Sleep (System. Threading. Timeout. Infinite) to bring the Thread into Sleep state. In particular, the call's Sleep time is uncertain. To Interrupt this sleep, you can call the Thread. Interrupt method.
Similar to sleep and interruption, it is suspended and restored. Suspending allows you to pause a Thread until another Thread calls Thread. Resume. The difference between sleep and suspension is that the latter does not immediately let the thread enter a waiting state, and the thread does not pause. NET runtime thinks that it is now a safe place to suspend it, and sleep will immediately let the thread enter a waiting state.
Finally, we will introduce Thread. Abort, which will stop the execution of a Thread. In our simple example, if you want to add a button to stop processing, it is very easy to call the Thread. Abort method, as shown below:
Private Sub Button2_Click (ByVal sender As System. Object ,_
ByVal e As System. EventArgs) Handles Button2.Click
T. Abort ()
End Sub
This is the power of multithreading. The response to the user interface is good because it runs in a separate thread, while the background processing runs in another thread. When you press the cancel button, the user will immediately receive a response and stop processing.
Transfer Data through multi-threaded programs
The above example is just a simple application. During programming, you also need to use many complex features of multithreading. One of the problems is how to pass in or out program data from the constructor of the thread class. That is to say, you cannot pass parameters to the data stored in another thread, it cannot return values. This is because the process you pass in to the thread constructor cannot have any parameters or return values. To solve this problem, you can encapsulate your process into a class so that the parameters of the method can use fields in the class.
Here is a simple example. If we want to calculate the square of a number, that is:
Function Square (ByVal Value As Double) As Double
Return Value * Value
End Function
To use this process in a new thread, we encapsulate it into a class:
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Sub CalcSquare ()
Square = Value * Value
End Sub
End Class
Use the code to start the CalcSquare process on a new thread, as shown below:
Private Sub button#click (ByVal sender As System. Object ,_
ByVal e As System. EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass ()
T = New Thread (AddressOf oSquare. CalcSquare)
OSquare. Value = 30
T. Start ()
End Sub
Note that after the thread starts, we do not check the square Value in the class, because even if you call the start method of the thread, you cannot ensure that the method is executed immediately. There are several methods to get the value from another thread. The method used here is the simplest, that is, to trigger an event when the thread completes. We will discuss another method in the subsequent thread synchronization. The following code adds the event declaration to SquareClass.
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Event ThreadComplete (ByVal Square As Double)
Public Sub CalcSquare ()
Square = Value * Value
RaiseEvent ThreadComplete (Square)
End Sub
End Class
The method for capturing events in the call code is similar to VB6. You still need to declare the WithEvents variable and process the event in a process. The difference is that the Handles keyword is used when you declare the event processing process, rather than the Object_Event commonly used in VB6.
Dim WithEvents oSquare As SquareClass
Private Sub button#click (ByVal sender As System. Object ,_
ByVal e As System. EventArgs) Handles Button1.Click
OSquare = New SquareClass ()
T = New Thread (AddressOf oSquare. CalcSquare)
OSquare. Value = 30
T. Start ()
End Sub
Sub SquareEventHandler (ByVal Square As Double )_
Handles oSquare. ThreadComplete
MsgBox ("The square is" & Square)
End Sub
For this method, you must note the process of processing the event. In this example, SquareEventHandler runs in the thread that generates the event. It is not running in the thread of table execution.
Synchronization thread
In terms of thread synchronization, VB. NET provides several methods. In the above square example, You need to synchronize with the thread that executes the computation so that you can wait for it to finish execution and get the result. In another example, if you sort an array in other threads, you must wait for the processing to complete before using the array. To perform these synchronization, VB. NET provides the SyncLock statement and the Thread. Join method.
SyncLock can get a unique lock referenced by an object, as long as it is transmitted to SyncLock. By getting this unique lock, you can ensure that multiple threads do not access the shared data or the Code executed on multiple threads. To get a lock, you can use a convenient object-the System. Type object associated with each class. You can use the GetType method to obtain the System. Type object:
Public Sub CalcSquare ()
SyncLock GetType (SquareClass)
Square = Value * Value
End SyncLock
End Sub
The other is the Thread. Join method, which allows you to wait for a specific time until a Thread completes. If the Thread is completed before the specified time, True is returned for Thread. Join. Otherwise, False is returned. In the square example, if you do not want to use the method to trigger the event, you can call the Thread. Join method to determine whether the calculation is complete. The Code is as follows:
Private Sub button#click (ByVal sender As System. Object ,_
ByVal e As System. EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass ()
T = New Thread (AddressOf oSquare. CalcSquare)
OSquare. Value = 30
T. Start ()
If t. Join (1, 500) Then
MsgBox (oSquare. Square)
End If
End Sub
For this method, you must note the process of processing the event. In this example, SquareEventHandler runs in the thread that generates the event. It is not running in the thread of table execution.