Threads in Visual Basic (Article, With Example)

Category:
System/API
Type:
Snippets
Difficulty:
Advanced

Author: David Nishimoto

Version Compatibility: Visual Basic 6

More information:
Introduction to using multiple threads in VB6. For more detailed information, see Daniel Appleman's article A Thread to Visual Basic.

Instructions: Copy the declarations and code below and paste directly into your VB project.

Scope

Threads provide an concurrent environment to
accomplish multiple tasks. The cpu time-shares
between each thread based on a priority number. The
higher the priority number the more frequent the
process is time-shared into the kernel address space. 
Each three has its own stack.
Once a thread begins to execute it can run
indefinitely or until the thread has been terminated. 
Internal to a thread function is a looping structure. 
The looping structure continues to loop until a
signal is set. The ellasped time to wait for an
incoming signal can be adjusted slowing down the
frequency of the looping cycle.
Since threads can process critical paths of
instruction and more then one thread can be started
concurrent tasking can occur.

Background

Two threads are created to run into the address
space.
AddressOf provides the address for the function to
assign to the thread
lThreadHandle1 and lThreadHandle2 are the thread
handles to terminate the thread.

lThreadHandle1 = CreateThread(ByVal 0&, ByVal 0&,
AddressOf test_function, ByVal 0&, 0, lpThreadID)
lThreadHandle2 = CreateThread(ByVal 0&, ByVal 0&,
AddressOf test_function2, ByVal 0&, 0, lpThreadID)

A event single is created
lEventHandle = CreateEvent(ByVal 0&, False, False,
ByVal 0&)

A signal is generated for an event.
lRC = SetEvent(lEventHandle)

The WaitForSingleObject receives the signal handle
and waits for an incoming signal. If the
signal is received ret is assigned a value not equal
to 0.

ret = WaitForSingleObject(lEventHandle, 10)


Assumptions:

1) Do not run the vb thread application from debug. 
Run the application as a compiled executable.
Instead compile and run the executable.

Call TerminateProcess(GetCurrentProcess, ByVal 0&)
will terminate the current vb process

2) Test each function first before embedding into the
thread frame work application.

3) Make sure the project is compiled as P-Code
(executable will fault if the binary is not P-Code)

Visual Basic Sample:

Module:
The module code has two functions define:
test_function and test_function2 which are associated
to a thread. The thread remains in the critical path
until a signal is received. Once the signal is
received the thread finish executing the critical path
and terminates.

Option Explicit
Public Declare Function CreateThread Lib "kernel32"
(ByVal lpThreadAttributes As Any, ByVal dwStackSize As
Long, ByVal lpStartAddress As Long, lpParameter As
Any, ByVal dwCreationFlags As Long, lpThreadID As
Long) As Long
Public Declare Sub Sleep Lib "kernel32" (ByVal
dwMilliseconds As Long)
Public Declare Function TerminateThread Lib "kernel32"
(ByVal hThread As Long, ByVal dwExitCode As Long) As
Long
Public Declare Function TerminateProcess Lib
"kernel32" (ByVal hProcess As Long, ByVal uExitCode As
Long) As Long
Public Declare Function GetCurrentProcess Lib
"kernel32" () As Long

Public Declare Function WaitForSingleObject Lib
"kernel32.dll" (ByVal hHandle As Long, ByVal
dwMilliseconds As Long) As Long
Public Declare Function CreateEvent& Lib "kernel32"
Alias "CreateEventA" (ByVal lpEventAttributes As Long,
ByVal bManualReset As Long, ByVal bInitialState As
Long, ByVal lpname As String)

Public lThreadHandle1 As Long
Public lThreadHandle2 As Long
Public lEventHandle As Long

Public Sub Main()

frmOutput.Show

End Sub

Public Sub test_function()
Dim i As Long
Dim ret As Long

i = 0


Do
i = i + 1

'Sleep 10
frmOutput.txtStream1 = i

DoEvents
ret = WaitForSingleObject(lEventHandle, 10)
Loop Until ret = 0


End Sub

Public Sub test_function2()
Dim i As Long
Dim ret As Long
i = 0

Do
i = i + 1
'Sleep 500
frmOutput.txtStream2 = i


ret = WaitForSingleObject(lEventHandle, 500)
Loop Until ret = 0

End Sub


Form:

The form contains two command buttons to start and
stop the thread. When the command button is
pressed the thread for test_function is created, a
second thread for test_function2 is created, and a
event object used to signal termination of all looping
is created. When the stop button is pressed, a signal
is broadcast for the event object handle and the
thread handles are terminated.


Private Sub cmdStart_Click()
Dim lpThreadID As Long

lThreadHandle1 = CreateThread(ByVal 0&, ByVal 0&,
AddressOf test_function, ByVal 0&, 0, lpThreadID)
lThreadHandle2 = CreateThread(ByVal 0&, ByVal 0&,
AddressOf test_function2, ByVal 0&, 0, lpThreadID)
lEventHandle = CreateEvent(ByVal 0&, False, False,
ByVal 0&)

End Sub

Private Sub cmdStop_Click()
Dim lRC As Long

lRC = SetEvent(lEventHandle)

If lThreadHandle1 > 0 Then
Call TerminateThread(lThreadHandle1, ByVal 0&)
End If
If lThreadHandle2 > 0 Then
Call TerminateThread(lThreadHandle2, ByVal 0&)
End If

lThreadHandle1 = 0
lThreadHandle2 = 0

End Sub

Private Sub Form_Unload(Cancel As Integer)

If lThreadHandle1 > 0 Then
Call TerminateThread(lThreadHandle1, ByVal 0&)
End If
If lThreadHandle2 > 0 Then
Call TerminateThread(lThreadHandle2, ByVal 0&)
End If

Call TerminateProcess(GetCurrentProcess, ByVal 0&)

End Sub