-
1 Attachment(s)
VB6 Threading, using the small DirectCOM.dll-HelperLib
Just for those who want to try a proven approach, which works reliably (and comparably simple)
in spanning up STAs (Single-Threaded-Apartments) for over 10 years now (one can use his own
VB6-compiled AX-Dlls which provide a Class-Instance that runs on said STA - no Assembler-Thunking,
no TypeLibs and also no "special Dll-Exports" are needed - it's aside from a few API-calls just straight VB-Code).
The Thread-Class-Instances in question are always created Regfree in this case (so,
no Setup is needed - just ship your Thread-Dlls alongside DirectCOM.dll in a SubFolder
of your App).
The Demo here tries to show not only how to create the STA-threads with a Class-
Instance in it, but also how to share Memory with the Applications Main-Thread
(which is the fastest way of cross-thread-communication).
The implementation of the Main-App is using a separate (Private) Wrapper-Class
for handling the "Remote-Thread" (offering Properties to wrap the shared Memory-area,
and such a Class will also automatically close the thread it wraps, in case it is itself terminated).
That allows for cleaner Code in the "Thread-consuming-instance" (in our case the Apps fMain-Form).
The Code for the ThreadLib.dll on the other hand - (this is the AX-Dll which provides a Public
cThread-Class, which will finally run on its own threaded Apartment) - is contained in the
\Bin\... SubFolder of the Zip.
Just leave this Bin-SubFolder as it is, when you run the Main-Apps *.vbp File.
Here's the Code for the Demo:
Attachment 126845
And here is a ScreenShot (the colored Forms are created inside the 4 Threads - and perform
an endless loop, to show some kind of "Plasma-Effect" - just to put the threads under stress a bit).
http://vbRichClient.com/Downloads/VB...gDirectCOM.png
Have fun (and just ask when you have any questions - though I tried to comment the Demo well enough, I hope).
Olaf
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Hello Schmidt! Thanks for cool code! it supported events?
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
The trick
Hello Schmidt! Thanks for cool code! it supported events?
No - the Demo above does not support "Classic VB-Events" currently (the higher-level
Threading-Support of the vbRichClient5.dll would allow for that though).
But the Demo as it currently is, supports "shared state" (over the shared Memory-Area,
behind the VB-Array TI() - which both sides have access to).
So, "Event-like reactions to State-Changes" can be implemented quite easily...
And the Demo does so already, by reporting in the Main-Form the state-changes
on the FPS-Member of the shared Mem-area - and in the opposite direction,
by reacting within the Threads to a state-change in the CancelThread-member
when it was set in the Main-Thread.
Olaf
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
No - the Demo above does not support "Classic VB-Events" currently (the higher-level
Threading-Support of the vbRichClient5.dll would allow for that though).
I am very interested in Threading-Support in RC5. Is there an example for this?
Thanks for the great work you've done here.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Olaf, also a bit interested for a specific purpose. Any suggestions welcomed.
Scenario: image format. Manually parsing file to extract animation frames, frames composed to an image-strip. The image strip is basically a 32bpp bitmap data, bytes only, ( (FrameWidth* frameCount) x FrameHeight) and will be contained in COM stream
I imagine myself using threading to create this image-strip in the background. The COM stream is created on the main thread but populated from the background thread. The COM stream is not guaranteed to be accessible by hGlobal, may be virtual via IStorage. A timer on the main thread can check for a flag set by the background thread when task is completed.
Are COM objects shareable between the main thread and background thread? Any tips on GDI+ usage between threads and sharing of GDI+ object handles?
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
LaVolpe
Are COM objects shareable between the main thread and background thread? Any tips on GDI+ usage between threads and sharing of GDI+ object handles?
For the latter question: GDI+ is "partially" thread-safe. You can access objects from multiple threads, but you must perform your own synchronization.
-
2 Attachment(s)
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
LaVolpe, i've made the example for you, but only it use the my methods of multithreading.
This program scans the specified directory and retrieves the thumbnails of the pictures from this directory. The pixels data of each thumbnail is stored to an IStream object (rather the object that support IStream interface). Since the size and the pixels format of the all thumbnails is indentical, you can simply calculate the offset (Width(Stride)*Height*BitsPerPixels\8). All work performs in the different thread. Main thread gets the notifications. All code doesn't contain the error handlers and other checks because it is example.
Code:
Option Explicit
Public Const ThumbnailSize As Long = 128
Public Enum UserMessages
SET_LABEL_CAPTION = WM_APP
SET_PROGRESS
ADD_TO_LIST
End Enum
Public Type UserData
NotifyWnd As Long
FindPath As Long
Stream As IStream
Progress As Single
End Type
Public Type ThreadData
NotifyWnd As Long
FindPath As String
Stream As IStream
Progress As Single
End Type
Public Function BackgroundThread( _
ByRef param As ThreadData) As Long
Dim fso As FileSystemObject
Dim curFolder As Folder
Dim curFile As File
Dim gdipToken As Long
Dim gdipStartup As GdiplusStartupInput
Dim image As Long
Dim thumb As Long
Dim rc As RECTL
Dim bd As BitmapData
Dim fileIndex As Long
Dim pointer As Long
gdipStartup.GdiplusVersion = 1
GdiplusStartup gdipToken, gdipStartup
Set fso = New FileSystemObject
Set curFolder = fso.GetFolder(param.FindPath)
rc.Right = ThumbnailSize
rc.Bottom = ThumbnailSize
For Each curFile In curFolder.Files
' // Set label caption
PostMessage param.NotifyWnd, SET_LABEL_CAPTION, Len(curFile.Name), ByVal SysAllocString(ByVal StrPtr(curFile.Name))
' // Open image
If GdipLoadImageFromFile(StrPtr(curFile.Path), image) = 0 Then
If GdipGetImageThumbnail(image, ThumbnailSize, ThumbnailSize, thumb) = 0 Then
If GdipBitmapLockBits(thumb, rc, ImageLockModeRead, PixelFormat32bppARGB, bd) = 0 Then
pointer = param.Stream.Seek(0, STREAM_SEEK_CUR) * 10000
param.Stream.Write ByVal bd.scan0, bd.stride * bd.Height
param.Progress = fileIndex / curFolder.Files.count
PostMessage param.NotifyWnd, SET_PROGRESS, param.Progress * 100, ByVal 0&
PostMessage param.NotifyWnd, ADD_TO_LIST, pointer, ByVal SysAllocString(ByVal StrPtr(curFile.Name))
GdipBitmapUnlockBits thumb, bd
End If
GdipDisposeImage thumb
End If
GdipDisposeImage image
End If
fileIndex = fileIndex + 1
Next
PostMessage param.NotifyWnd, SET_PROGRESS, 100, ByVal 0&
param.Progress = 1
End Function
This function is performed in the background thread. I've used the similar types ThreadData and UserData in oreder to avoid string freeing in the main thread.
Code:
Option Explicit
Dim WithEvents WndHook As clsTrickSubclass2
Dim ThreadData As UserData
Private Sub cmdSplit_Click()
Dim hThread As Long
Set ThreadData.Stream = Nothing
CreateStreamOnHGlobal 0, True, ThreadData.Stream
ThreadData.NotifyWnd = Me.hWnd
ThreadData.FindPath = SysAllocString(ByVal StrPtr(txtPath.Text))
ThreadData.Progress = 0
hThread = vbCreateThread(0, 0, AddressOf BackgroundThread, VarPtr(ThreadData), 0, 0)
CloseHandle hThread
If hThread Then
cmdSplit.Enabled = False
lstImages.Enabled = False
lstImages.Clear
End If
End Sub
Private Sub Form_Load()
Set WndHook = New clsTrickSubclass2
WndHook.Hook Me.hWnd
End Sub
Private Sub lstImages_Click()
Dim pointer As Long
Dim bitmap As Long
Dim gr As Long
Dim dat() As Byte
If ThreadData.Progress <> 1 Or lstImages.ListIndex < 0 Then Exit Sub
pointer = lstImages.ItemData(lstImages.ListIndex)
ReDim dat(ThumbnailSize * ThumbnailSize * 4 - 1)
ThreadData.Stream.Seek CCur(pointer) / 10000@, STREAM_SEEK_SET
ThreadData.Stream.Read dat(0), UBound(dat) + 1
picThumbnail.Cls
If GdipCreateBitmapFromScan0(ThumbnailSize, ThumbnailSize, ThumbnailSize * 4, PixelFormat32bppARGB, dat(0), bitmap) = 0 Then
GdipCreateFromHDC picThumbnail.hdc, gr
GdipDrawImageI gr, bitmap, (picThumbnail.ScaleWidth - ThumbnailSize) \ 2, (picThumbnail.ScaleHeight - ThumbnailSize) \ 2
GdipDisposeImage bitmap
GdipDeleteGraphics gr
picThumbnail.Refresh
End If
End Sub
Private Sub WndHook_WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long, Ret As Long, DefCall As Boolean)
Dim tmpStr As String
Select Case Msg
Case UserMessages.SET_LABEL_CAPTION
GetMem4 lParam, tmpStr
lblProgress.Caption = tmpStr
Case UserMessages.SET_PROGRESS
picProgress.Cls
picProgress.Line (0, 0)-(wParam, 1), , BF
If wParam = 100 Then
cmdSplit.Enabled = True
lstImages.Enabled = True
End If
Case UserMessages.ADD_TO_LIST
GetMem4 lParam, tmpStr
lstImages.AddItem tmpStr
lstImages.ItemData(lstImages.NewIndex) = wParam
End Select
End Sub
The modules modMultiThreading.bas and EXEInitialize.tlb you can download hereand clsTrickSubclass2.cls here.
Attachment 134237
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
@The Trick. I'll download and play this weekend. In my case, I will not have a hWnd to pass. My intent is background threading in a windowless usercontrol and not too sure I want to subclass the control's container. I know I can create an API window, i.e., Static window class for example, for this purpose instead. However, your comments for your vbCreateThread function states it will not work in IDE? Is that still correct?
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
LaVolpe
In my case, I will not have a hWnd to pass. My intent is background threading in a windowless usercontrol and not too sure I want to subclass the control's container.
hWnd is needed only for communication between threads. You can use flag or something else (system Event or Mutex). If you don't worry about the additional dependencies (tlb or dll), you can use the object in background thread and generate event to main (if you had read the my first article about multithreading, there is the example).
Quote:
Originally Posted by
LaVolpe
I know I can create an API window, i.e., Static window class for example, for this purpose instead.
HWND_MESSAGE, also you can use any method of the calling in the specified context. Using window i ensure the manual marshaling. You can use any other methods.
Quote:
Originally Posted by
LaVolpe
However, your comments for your vbCreateThread function states it will not work in IDE? Is that still correct?
This function will perform in same thread in IDE, because IDE doesn't support the multithreading debug (i mean not-compiled code). You can create the dll, and debug in the ide through CreateThread, here is example.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
The Trick:
I find it so difficult to understand the code and comments here. Is there a newbie-friendly thread regarding multithreading stuff in VB6. I'd really like to learn and use. I know it involves some basic(maybe advanced?) knowledge of COM, and I have read some articles from MSDN about it, but still I am having trouble here.
I understand that to fully know how it works takes more time but right now I just hope to find something that I can use right away. My current problem is to send HTTP requests asynchronously, wait for each response, and process them after all response are received. This will accelerate my program a bit I guess.
Olaf:
I checked classes in RC5 and got:
Code:
cThreadHandler
cThreadInit
cThreadMethods
cThreadProxy
seems they work with:
Quote:
cRegFree
'The DirectCOM methods are also incorporated in RC5?
An easy example will be much appreciated!!
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
bPrice
The Trick:
I find it so difficult to understand the code and comments here. Is there a newbie-friendly thread regarding multithreading stuff in VB6. I'd really like to learn and use. I know it involves some basic(maybe advanced?) knowledge of COM, and I have read some articles from MSDN about it, but still I am having trouble here.
I don't understand why did you say COM. I you want to use the threads you unnecessarily use COM.
Newbir-friendly? Look at this:
http://www.vbforums.com/showthread.p...-of-Native-DLL
http://www.vbforums.com/showthread.p...n-Standart-EXE
In the first example you can debug the threads in IDE, but you need to use the additional DLL. Second example involves the simple stuff like find prime numbers in new thread etc. Unfortunately in this case the treads don't work in IDE (all examples work in Main thread), after compiling they work in the new thread.
Quote:
Originally Posted by
bPrice
I understand that to fully know how it works takes more time but right now I just hope to find something that I can use right away. My current problem is to send HTTP requests asynchronously, wait for each response, and process them after all response are received. This will accelerate my program a bit I guess.
For asynchronously request you unnecessarily use threads, you can use XMLHTTP and asynchronous
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
The trick
That's not newbie-friendly at all...
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Olaf, I read another thread where you commented. Thanks for all the example code there. Still:
Quote:
The simplest way to create Thread-STAs in VB6 is still per ActiveX-Exe,
or per DirectCOM.dll (harder) - or with the RC5-cThreadHandler-Class (easier again).
I'd very much like to have an example of threading related classes in RC5... At present, I am trying my best to experiment with ActiveX-Exe, but I am not sure whether it will be easy for deployment.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
bPrice
That's not newbie-friendly at all...
If it isn't for newbie then i can't help anything:
Code:
Private Sub cmdNewWnd_Click()
Dim hThread As Long
Dim capt As String
Dim lpCapt As Long
capt = InputBox("Window title", "")
lpCapt = SysAllocString(StrPtr(capt))
hThread = vbCreateThread(0, 0, AddressOf NewThreadProc, lpCapt, 0, 0)
CloseHandle hThread
End Sub
Public Function NewThreadProc(ByVal value As String) As Long
Dim frm As Form
Set frm = New frmTest1
frm.Caption = value
frm.Show vbModal
End Function
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
The trick
If it isn't for newbie then i can't help anything:
Code:
Private Sub cmdNewWnd_Click()
Dim hThread As Long
Dim capt As String
Dim lpCapt As Long
capt = InputBox("Window title", "")
lpCapt = SysAllocString(StrPtr(capt))
hThread = vbCreateThread(0, 0, AddressOf NewThreadProc, lpCapt, 0, 0)
CloseHandle hThread
End Sub
Public Function NewThreadProc(ByVal value As String) As Long
Dim frm As Form
Set frm = New frmTest1
frm.Caption = value
frm.Show vbModal
End Function
Wow it seems quite handy indeed, if it's only for making use. Usually I will have to at least understand a bit how it works and that's when all the APIs and C-like datatypes(sometimes assemblies) ... seem formidable.
VbCreateThread is from here right? I'll try again ...
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
VbCreateThread is from here right? I'll try again ...
Yes, it is. Also there is the dll that you can use to the simple implementation threading for debugging purposes. Just in order to don't include the module and tlb at the debugging time.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
bPrice
I checked classes in RC5 and got:
Code:
cThreadHandler
cThreadInit
cThreadMethods
cThreadProxy
Only the first one (cThreadHandler) is needed in the "higher-level"-RC5-Threading-support
(the others are helper-Classes only, which you don't come into contact with "on the outside").
Quote:
Originally Posted by
bPrice
seems they work with: cRegFree
'The DirectCOM methods are also incorporated in RC5?
Yes, once you have instantiated (kind of "bootstrapped") the New_c (of type cConstructor)
regfree per direct API-call using a Declare-Statement for DirectCOM.dll (GetInstancEx), you
can then use New_c.Regfree to instantiate all kind of "other COM-Dlls" more conveniently:
- either in the current Thread per New_C.Regfree.GetInstanceEx -
- or on an entirely new Thread per New_c.Regfree.ThreadObjectCreate
Quote:
Originally Posted by
bPrice
An easy example will be much appreciated!!
Posted one finally into the CodeBank here:
http://www.vbforums.com/showthread.p...-ThreadHandler
Maybe you found it already.
Olaf
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
LaVolpe
Olaf, also a bit interested for a specific purpose. Any suggestions welcomed.
Scenario: image format. Manually parsing file to extract animation frames, frames composed to an image-strip. The image strip is basically a 32bpp bitmap data, bytes only, ( (FrameWidth* frameCount) x FrameHeight) and will be contained in COM stream
I imagine myself using threading to create this image-strip in the background. The COM stream is created on the main thread but populated from the background thread. The COM stream is not guaranteed to be accessible by hGlobal, may be virtual via IStorage. A timer on the main thread can check for a flag set by the background thread when task is completed.
Are COM objects shareable between the main thread and background thread? Any tips on GDI+ usage between threads and sharing of GDI+ object handles?
Are you still interested in using DirectCOM.dll to solve this -
or did you already managed a solution (using Tricks stuff)?
As far as Stream-Instances are concerned, these should be threadsafe, even when passed
(per Pointer) among threaded STAs - just ensure proper synchronization on your own -
not so sure about GDI+ Handles and methods about their thread-safety (when passed
as Pointers between STAs)... I'd create a basic "GDI+ environment" within *each* Threads
STA to be on the safe side - and use the GDI+ calls within that STA only on GDI+ Handles
created within said STA - that should work safely.
Olaf
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Hi Olaf,
First I have to say, I'm a big fan of your work. I have been using Cairo and RC5 since it was called dhRichClient3. Thank you for that.
Now my question about this subject: I spent a lot of time trying to figure out why my code was not working and finally I think I found the problem. I was trying to pass String variables (several of them actually) between the thread and the main application inside of the ThreadInitDirectCOM type. And I noticed that as soon as I add string variables there, the thread does not gets loaded.
1st question: Can I use string variables inside of Type ThreadInitDirectCOM ?
If not - can I pass my strings as byte array and is there a limitation on the size?
(I'm not going to pass anything crazy like megabytes of data, just a couple of kilobytes at the most)
And 2nd question: Is the Reserved(0 To 127) As Long array reserved for some internal use? Or was it just a part of example and can it be deleted?
Thanks.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
To your second question first...
The current (0 to 127) "Reserved-Space" Long-Array is perhaps a bit generous (and currently not used fully),
but the entry needs to exist...
To your other question, regarding "BSTR-types in the shared Mem-Area TypeDef"...
These are possible, but since BSTRs are "RefTypes", they'll allocate memory sidewards into their "Pointer-Slot" within the UDT.
And this Operation has to be made threadsafe, by protecting the read-and write-ops with:
- either Mutexes o.a. (when the shared-memory-area was created for cross-process-access)
- or as in our case via CriticalSections (where we share the mem-area InProcess-cross-thread)
Below comes replacement code, which demonstrates that:
Into the Exe-Project-Class cThreadWrapper:
Code:
Option Explicit 'it's a good idea, to wrap your Remote-Threads in its own Wrapper-Class
Private Type ThreadInitDirectCOM
Param As Long 'User-Param (given into the ThreadMain-Method of the COM-Dll)
hThread As Long 'filled from Thread (instantly, after STARTCOMOBJECT() returns)
ThreadID As Long 'filled from Thread (if fully initialized, some msec after STARTCOMOBJECT())
Reserved(0 To 127) As Long
'userdefined Params can be placed here...
aCS(0 To 7) As Long 'CriticalSection-range in a size sufficient also for 64Bit-API-calls (the mainthread should init this)
FPS As String 'will reflect the current FPS of the Remote-Thread
CancelThread As Boolean 'will be used to signalize Thread-Cancelling to the Remote-Thread
End Type
'this is the call which ensures a new STA with a regfree loaded AX-Dll-Class-Instance in it...
Private Declare Function STARTCOMOBJECT Lib "DirectCom" (FName As String, ClassName As String, TI As Any) As Long
'and below just some accompanying APIs we use here in the wrapper-class, to handle the Memory-Sharing and the Closing of the Remote-Thread
Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (Arr() As Any) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal mSec As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Sub InitializeCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private Declare Sub DeleteCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private Declare Sub EnterCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private Declare Sub LeaveCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private TI() As ThreadInitDirectCOM 'will host the TI-allocation, which we create here in the Main-Thread
Private Sub Class_Initialize() 'prepare the TI-Array (which has only a single "Index-Slot" and is shared with the Remote-Thread)
ReDim TI(0 To 0) 'we allocate the SharedMem-Array here in the Main-Thread
TI(0).Param = ArrPtr(TI) 'the Param-Member is, what gets passed into the ThreadMain-Function of the Remote-Class
InitializeCriticalSection TI(0).aCS(0) 'init the Critical Section on the allocation .aCS
End Sub
Public Sub StartThread()
STARTCOMOBJECT App.Path & "\Bin\ThreadLib.dll", "cThread", ByVal VarPtr(TI(0)) 'start the Thread along with the ThreadLib.dll-cThread-Class regfree
End Sub
Public Property Get ThreadID() As Long
ThreadID = TI(0).ThreadID '<- the .ThreadID-member of TI gets filled in the upstarting Remote-Thread
End Property
Public Property Get FPS() As String
EnterCriticalSection TI(0).aCS(0) 'BSTR-member-access has to be protected via CriticalSections (in Read, as well as in Write-Direction)
FPS = TI(0).FPS '<- the .FPS-StringMember of TI gets filled and updated in the Remote-Thread via Property-Let
LeaveCriticalSection TI(0).aCS(0)
End Property
Private Sub Class_Terminate() 'this ensures, that the Remote-Thread-Class dies along with this Wrapper-Class
TI(0).CancelThread = True 'signalize the Remote-Thread, that we want to close it
Sleep 50 'give the Remote-Thread some time, after we signaled it to close itself (in the line above)
CloseHandle TI(0).hThread 'just to avoid Handle-Leakage
DeleteCriticalSection TI(0).aCS(0) 'delete the CriticalSection
End Sub
And this into the ThreadLib-Project-Class cThread:
Code:
Option Explicit
Private Declare Sub BindArray Lib "kernel32" Alias "RtlMoveMemory" (PArr() As Any, ByVal pSrc&, Optional ByVal CB& = 4)
Private Declare Sub ReleaseArray Lib "kernel32" Alias "RtlMoveMemory" (PArr() As Any, Optional pSrc& = 0, Optional ByVal CB& = 4)
Private Declare Sub EnterCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private Declare Sub LeaveCriticalSection Lib "kernel32" (CS_20_or_32Byte As Any)
Private Type ThreadInitDirectCOM
Param As Long 'User-Param (given into the ThreadMain-Method of the COM-Dll)
hThread As Long 'filled from Thread (instantly, after STARTCOMOBJECT() returns)
ThreadID As Long 'filled from Thread (if fully initialized, some msec after STARTCOMOBJECT())
Reserved(0 To 127) As Long
'userdefined Params can be placed here...
aCS(0 To 7) As Long 'CriticalSection-range in a size sufficient also for 64Bit-API-calls (the mainthread should init this)
FPS As String 'will reflect the current FPS of the Remote-Thread
CancelThread As Boolean 'will be used to signalize Thread-Cancelling to the Remote-Thread
End Type
Private TI() As ThreadInitDirectCOM
Public Function ThreadMain(ByVal Param As Long) As Long
BindArray TI, Param 'span TI virtually over the same Memory as occupied by the TI-Array which was allocated in the Main-Threads ThreadWrapper-Class
Set fThread.Thread = Me 'hand a reference of this Class-Instance over into the Thread-Form too
fThread.Caption = "ThreadID: " & App.ThreadID 'update the ThreadForms Caption with the ThreadID of this Thread
fThread.Show vbModal 'show the ThreadForm modally
Set fThread.Thread = Nothing
ReleaseArray TI 'avoid double-freeing (since the TI-Array is already freed in the MainThreads ThreadWrapper-Instance)
End Function
Friend Property Let FPS(ByVal RHS As String) 'a Let-Property for the Write-Direction (Information, updated from this Thread here)
EnterCriticalSection TI(0).aCS(0) 'BSTR-member-access has to be protected via CriticalSections (in Read, as well as in Write-Direction)
TI(0).FPS = RHS 'now we can update the shared-memory BSTR-Member (to give an example, how we transport Info from here into the Main-Thread)
LeaveCriticalSection TI(0).aCS(0)
End Property
Friend Property Get Cancelled() As Boolean 'a Get-Property for the Read-Direction on the Shared-Memory-Array (reading a member which is updated from the Main-Thread)
Cancelled = TI(0).CancelThread 'so, here's the opposite to FPS (we access the CancelThread-Member, to detect when the Main-Thread wants us to close)
End Property
HTH
Olaf
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Thank you so much, Olaf.
I will use your code.
-
Re: VB6 Threading, using the small DirectCOM.dll-HelperLib
Quote:
Originally Posted by
NetChain
Thank you so much, Olaf.
I will use your code.
Ok, though in case you "expand on the little demo" a bit, I'd suggest
to place the (currently identical, but "defined separately") SharedUDT-Definition -
in its own *.bas module (e.g. named: modSharedTypes.bas, making the Type Public there)...
Then place the same "file-reference" to this new 'modSharedTypes.bas' module
in both projects (the Main-StdExe- as well as the ThreadHelper-Dll-Project),
so that in case of UDT-changes, you wont have to "synchronize them manually" in the other Project.
Olaf