Use multithreading in your VB.NET application
For a long time, developers have been demanding that Microsoft adds more thread function to VB - this is finally realized in VB.NET. VB6 does not support creating multi-threaded EXE, DLL, and OCX. However, this phrase is easy to cause misunderstandings because VB6 supports the execution of multiple single-threaded units. A unit is actually a location executed, and the boundary of the unit limits access to the interior of the unit.
VB.NET supports an application that creates a free thread. This means that multiple threads can access the same shared data set. This article will lead you to understand the basic content of multi-thread.
Although VB supports multiple single-threaded units, it does not support free thread models that allow multiple threads run on the same data set. In many cases, new threads that generate a background handler will increase the availability of the application. One is clear that when an executing a long procedure that may stop the response, you will want to place a cancel button on the form.
Solution
Because VB.NET is running when using public language runtime, it enhances many new features, one of which is the ability to create a free thread application.
In VB.NET, it is easy to work with threads. We will explore some exquisiteness later, let's create a simple form that generates a new thread that performs the background handler. The first thing we need to do is the background handler that we want to run on the new thread. The following code performs a quite long running process - an infinite loop:
Private subupgroundprocess ()
DIM i as integer = 1
Do While True
ListBox1.Items.Add ("Iterations:" i)
i = 1
Loop
End Sub
This code is infinitely looped and adds an entry to the list box on the form in each cycle. If you are not familiar with VB.Net, you will find something that you can't do in VB6 in this code:
l assigning DIM I as integer = 1 when declaring variables
l Use = operator i = 1 to replace i = i 1
l Call keyword has been removed
Once we have a work process, we need to assign this code to a new thread and start it. Complete this job, we need to use the Thread object, which is part of the system.threaming namespace in the .NET Framework class. When a new THREAD class is instantiated, we pass a reference, which points to the code block we want to execute in the constructor of the Thread class. The following code creates a new THREAD object and passes the reference to the BackgroundProcess to it:
Dim t as thread
T = New Thread (Addressof Me.BackgroundProcess)
T.Start ()
The AddressOf operator creates a delegate object for the BackgroundProcess method. Delegation is a type of secure, object-oriented function pointer in VB.NET. After the thread is instantiated, you can start executing the code by calling the thread's START () method.
Let the thread are under control
When the thread begins, you can perform certain controls on its status by using the THRead object. You can suspend the execution of the thread by calling thread.sleep method. This method receives a constant value indicating how long the thread will sleep. If you want to slow down the list box entry in the previous example, place a call to this method in the code:
Private subupgroundprocess ()
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 property that allows you to get a reference to the current running thread.
You can also make a thread in a time uncertain sleep state by calling Thread.Threading.Timeout.infinite. To interrupt this sleep, you can call the Thread.Interrupt method.
Similar to Sleep and Interrupt is Suspend and Resume. Suspend allows you to block a thread until another thread calls thread.resume. The difference between SLEEP and Suspend is that the latter is not immediately waiting for a thread. Determine the thread when the .Net runtime is before a secure suspend position, the thread will not hang. Sleep is immediately enters the waiting state.
Finally, Thread.abort aborts the execution of a thread. In our simple example, we also want to add another button that can make us stop the program. To do this, everything we need is to call the thread.abort method as described below:
Private sub button2_click (byval sender as system.object, _
Byval e as system.eventargs) Handles Button2.click
T.Abort ()
End Sub
It can be seen in this way. The user interface seems to be a response to the user because it runs in a thread and the background handler runs in another thread. The cancel button will immediately respond to the user's Click event simultaneous processing process is aborted.
Pass data through multi-threaded process
The previous example shows a relatively simple case. When you have programmed, there are many complicated issues that need to be solved. One problem you will encounter is to pass data to the process of passing to the Thread class constructor and from this process. In other words, you want to start on another thread can't receive any parameters and you can't return any data from this process. This is because the process passed to the thread constructor cannot have any parameters or return values. In order to avoid this problem, package your process into a class, in which the parameters of this method are indicated by a domain.
There is a simple example if we have a number of squares calculating a number:
Function Square (Byval Value As Double) AS DOUBLE
Return Value * Value
END FUNCTION
In order to make this process can be used in a new thread, we will pack 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 these code to launch the Calcsquare process in a new thread, the code is as follows:
Private sub button1_click (byval sender as system.Object, _
Byval e as system.eventargs) Handles Button1.click
DIM OSQUARE AS New SquareClass ()
T = new thread (address (addressof osquare.calcsquare)
Osquare.value = 30
T.Start ()
End Sub
Note When the thread starts, we don't check the class's square value, because it does not guarantee that once you call the thread START method, it will execute. There are some ways to get this value from another thread. The easiest way is to trigger an event when thread is completed. We will discuss another method in synchronization in the next part thread. The following code adds the event declaration for 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
Capturing this event in the call code is not much change compared to VB6, it is still used with the WitHevents declared variables and handles events during one process. The changed portion is the process of declaring the handling event with the Handles keyword and no longer uses a naming agreement like Object_Event in VB6.
Dim Withevents Osquare as SquareClass
Private sub button1_click (byval sender as system.Object, _
Byval e as system.eventargs) Handles Button1.click
Osquare = new SquareClass ()
T = new thread (address (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
One problem that needs attention is to pay the process of handling the event. In this example, SquareEventHandler is running in the thread that is incident, not the thread running in the form.
Thread synchronization
VB.NET contains some statements to provide synchronization of threads. In the Square example, you may want to synchronize the calculated thread to wait until the calculation is completed, so you can get the result. For another example, if you sort arrays in a separate thread and wait for this process to end before using this array. In order to achieve these synchronization, VB.NET provides the SyncLock statement and the thread.join method.
Synclock gets exclusive locks that are referenced to the object passed to it. By getting this exclusive lock, you can ensure that multiple threads do not access shared data or execute code on multiple threads. A SYSTEM.TYPE object that can be easily used to get lock-locked is associated with each class. You can get the System.Type object via the GetType method:
Public Sub Calcsquare ()
SyncLock gettype (SquareClass)
Square = value * Value
End synclock
End Sub
Finally, the thread.join method allows you to wait for a specific time until a thread ends. If the thread is completed before you determined, thread.join returns true, otherwise return false. In Square's example, if we don't want to trigger an event, you can call the thread.join method to determine if the calculation has ended. The code is as follows:
Private sub button1_click (byval sender as system.Object, _
Byval e as system.eventargs) Handles button1.clickdim OSquare as new squareclass ()
T = new thread (address (addressof osquare.calcsquare)
Osquare.value = 30
T.Start ()
IF T.JOIN (500) THEN
Msgbox (Osquare.square)
END IF
End Sub
Author: Matthew Arnheiter is a senior consultant at Hackensack (Hackensack) of GoAmerica Communications company, he was The Visual Basic Developer's Guide to Design Patterns and UML (Sybex, 2000) author of the book. You can contact him through (201 )996-1717 x2367 or marnheiter ◎ goamerica.net.