Search Tools Links Login

Even Better Multithreading with Low Overhead


Visual Basic 6, or VB Classic

Theres a code on PSC that says the best stable multithreading in vb6 is done with activex. I say thats the worst advice I've ever heard. This is one of my solutions.

Original Author: Robert Thaggard

Code

Easy multithreading with low overhead - Part 1


Srideep Prasad posted an article on how to do safe multithreading in vb6 with
multi instancing. His "solution" required making an activex exe and
making new instances of it for each thread which obviously is very processor
consuming and defeats the very purpose of multithreading. His reason for this
"solution" was "hey, at least theres no more doevents." Give
me a break. I'm dont understand how he code made it to code of the month list.


My solution is simple and has low overhead.


1. Create an api dll using visual c++. If you dont know how to program c++,
thats no problem. You can use my template.

2. Make a function that gets the address of the function you want to run in a
seperate thread.

3. From here you can either use the dll as code running in the background to
serve as a "airbag" so you can call CreateThread safely from in the
dll, or you can call the function by yourself in the dll by address. (This is
called a callback routine. Many enumerated functions in the windows api do
this.)



Part 1 of this tutorial will cover how to make a callback routine for your
multithreading.


The first step is to make a new Win32 Dynamic-Link Library workspace. Here is
my code template for an api dll.



#include <windows.h>
// This may be a little confusing to some people.
// All this next line does is specify a vb-safe calling convention
// CALLBACK* says that the variable type is actually a function, in this case a vb function
// THREADED_FUNC is the variable type that the function will be called in the dll. I could have put anything else in here
// typedef BOOL means that the function has a return value of boolean
// (int) means that the function has one paramater and its an integer. You could put as many of these as you need, depending
// on the number of parameters your function takes. ie your function takes an integer and two strings. You would put
// (int, LPCSTR, LPCSTR)

typedef BOOL (CALLBACK* THREADED_FUNC) (int);
// Function prototypes
void FreeProcessor(void);
LONG __declspec(dllexport) WINAPI MakeThread(THREADED_FUNC &pTFunc, int nPassedValue);
// Starting and ending point of the dll, required for every api dll
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// dll starts processing here
// inital values and processing should go here


}
else if (dwReason == DLL_PROCESS_DETACH)
{
// dll stops processing here
// all clean up code should go here


}
return 1;
}
// MakeThread - Function that calls function by address (This is the callback routine)
// This function accepts a THREADED_FUNC which is actually the address of the threaded function
// It also accepts the parameters your function takes which is an integer for this example. You will need to set the
// number of parameters to match the function you wrote

LONG __declspec(dllexport) WINAPI MakeThread(int nPassedValue, THREADED_FUNC &pTFunc)
{
// try-catch block for error handling
try
{
do
{
// call the function by address and examin return value
if (pTFunc(nPassedValue) == FALSE)
return 1;
FreeProcessor();
} while (true);
}
catch (int) { return 0; }
}
// FreeProcessor function written by Jared Bruni
void FreeProcessor(void)
{
MSG Msg;
while(PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
{
if (Msg.message == WM_QUIT)break;
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}



The next step is to create a export definitions file for MakeThread. This
is very simple.

LIBRARY MyFile

DESCRIPTION 'Callback multithreading dll for MyProgram'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE SINGLE



HEAPSIZE 4096

EXPORTS

?á?á?á MakeThread @1


I highlighted the LIBRARY line for a good reason. Make sure whatever you type
after LIBRARY is the name of the cpp file that your DllMain is in. For example
if your DllMain is in a file called "BigLousyDll.cpp", then you would
type LIBRARY BigLousyDll



Also make sure that the export definitions file is the same name as the cpp file
your DllMain is in. Like I said, if your DllMain is in a file called "BigLousyDll.cpp",
you would name your export definitions file BigLousyDll.def



Once you compile your dll, it should automatically be registered. I would put it
in your system or system32 folder so you don't have to type a explicit path to
it in your vb file.


Public Declare Function
MakeThread Lib "MyFile.dll" (lpCallback As
Any
, ByVal nInt As
Integer
) As Long

Public
i As Integer

Public
nTimes As Integer



Public Function
MyFunction(ByVal nValue As Integer) As Boolean

?á?á?á nTimes = nTimes + 1

?á?á If
nTimes > 0 Then

?á?á?á?á?á?á?á If i
< 20 Then

?á?á?á?á?á?á?á?á?á?á?á i = i + 1

?á?á?á?á?á?á?á End If

?á?á?á?á?á?á?á MyFunction = True?á?á?á
'Tells dll to keep running through function

?á?á?á?á?á?á?á Exit Function

?á?á?á Else


?á?á ?á?á?á?á i = nValue

?á?á?á?á?á?á?á MyFunction = True?á?á?á
'Tells dll to keep running through function

?á?á?á?á?á?á?á Exit Function

?á?á
End If

?á?á?á
MyFunction =
False?á?á?á
'Tells dll to stop

End Function



Sub
Main()

?á?á?á If Not MakeThread(AddressOf
MyFunction, 3) Then

?á?á?á?á?á?á?á MsgBox "Multithreading
error"

?á?á?á Else

?á?á?á?á?á?á?á MsgBox "Success"

?á?á?á End If

End Sub




If you find this code helpful, vote only if you want to. I dont care if I win
coding contest. I just thought this solution is excellent compared to what
Srideep Prasad posted.


About this post

Posted: 2002-06-01
By: ArchiveBot
Viewed: 136 times

Categories

Visual Basic 6

Attachments

No attachments for this post


Loading Comments ...

Comments

No comments have been added for this post.

You must be logged in to make a comment.