Results 1 to 23 of 23

Thread: VB6 Threading-Tutorial (Mandelbrot-Rendering)

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    VB6 Threading-Tutorial (Mandelbrot-Rendering)

    As the title says - a Tutorial (in 9 Steps - each step in its own Tutorial-Folder),
    which hopefully provides enough help with understanding "the builtin threading-support of VB6"
    (which is entirely based on COM-STAs).

    To describe the tutorial in a short way:
    - in Step0 we start with a normal StdExe-Project - rendering our Mandelbrot from "monolithic code in a *.bas module"
    - ... and finally end up (after Step 8) with a regfree deployable, portable threaded App in a Std-Exe

    Here is the Tutorial-Zip (with its 9 "Step"-Folders and the Tutorial_Readme.txt):
    MandelbrotThreadTutorial.zip

    When you go through the Tutorial-Folders:
    - please don't skip a Step
    - and please compile the Project in each Step (directly into the current Steps Project-Folder)
    - this way, the following steps will find the needed Binaries (Dlls) they depend on

    Ok, here a direct copy of what's contained also in the Tutorial-Readme (describing the 8 Steps in more detail):

    Step0 StdExe (an 'unsplit LongRunner'):
    - trying to cover, what's probably "a typical situation" and where it all starts...
    - the "problem-code" being contained in a "monolithic, straight longrunner-routine"...
    - which "just takes a bit too much time" (especially in the IDE)

    Step1 StdExe (ClassCode in ExeProject):
    - this is perhaps the most important Step to take, since for succesful threading...
    - you'll have to "split the problem" (your monolithic routine) up into "threadable chunks"
    - we do that in a Project-Private Class, ...
    - since we also plan to "move-out" this code (into a separate Dll later)
    - this is where you refine and test your new "chunkable" Routine, until it's solid
    - if your "chunkable worker-routine" has roughly the same speed as the former monolith, all's well

    Step2 Mandel-Dll (move ClassCode):
    - only after you're satisfied with the *stability* of your new Class(Methods), ...
    - should you move the Class-Code into its own Dll-Project (as a now Public Class),
    - to encapsulate it, and to gain perfomance by applying faster native Compiler-settings there
    (whilst your MainExe remains at slower and safer Compiler-settings,... even PCode will do)
    - this Project just needs to be compiled (into the local Project-Folder), to be able to proceed further with Step3 below

    Step3 StdExe (using Mandel-Dll, yet unthreaded):
    - demonstrates, how the StdExe-Project has to be changed and adapted for Dll-Class mode
    - profiting now from better performance (usually about factor 10-20) even in IDE-Mode...
    - and also reducing Code-volume in the Main-Project (faster Startup-Times, faster Intellisense)

    Step4 AxExe-Threading (cThreadHost):
    - shows, how to finally use the compiled Dll(Class) in a scenario with two threads
    - using VB6's already built-in threading support in AxExes (which - as shown - also support InProcess-Threading)
    - cThreadHost is the only Public Class in that AxExe (the one which will load our Dll-Worker-Class on its own Thread)
    - and to overcome the only "quirk" in AxExe-based threading -> the project also contains a small Form (fAsyncHelper.frm)
    - this little helper-form is used within cThreadHost, and provides "async decoupling of method-calls via PostMessage-API"
    - note, how the fMain.frm RedrawMandelBrotArea-routine was changed, compared to the previous example in Step 3:
    - instead "looping the stripes", RedrawMandelBrotArea now only triggers the first stripe on each ThreadHandler
    - the rest of the stripe-calculations will get triggered from within the two ThreadHandler-Events (for TH1 and TH2)

    Step5 AxExe-Threading (cThreadPool):
    - well, the last mentioned point in the descriptions for Step4 above, is the reason for Step5...
    - in Step4 each Thread(HandlerObject) had to be declared WithEvents - each Event then implemented separately
    - so, to avoid that, we introduce a new Class in this Project -> cThreadPool
    - which then allows basically "unlimited cThreadHandlers", providing us with a single Event (for all thread-jobs)
    - this ways the Code in our fMain.frm will get a bit lighter, despite using 3 Threads now
    - note, that cThreadHandler.cls and fAsyncHelper.frm are exact copies from the Step4-project (no changes there)

    Step6 STA-Dll (to support threading, similar to AxExes):
    - Ok, since the goal of this tutorial is, to finally show "regfree deployment of a threaded VB6-solution"...
    - this second Dll-Project will help us to achieve this goal, by providing AxExe-compatible STA-threading for StdExes
    - the AxExe-Project (from previous Step5) already tried to provide its threading support generically by:
    - using the two Classes cThreadHandler and cThreadPool in a way, to load "a secondary worker-dll" (MandelbrotLib.dll)
    - so, these two Classes are also contained in this Dll-Project (slightly changed, but offering similar functionality)
    - also this Dll-Project just needs to be compiled (into the local Project-Folder), to be able to proceed with Step7 below

    Step7 StdExe (using STA-Dll):
    - Well, we're nearly there ... this StdExe-Project is using the above ThreadedSTAs.dll -
    - to provide roughly similar Threading-support in our fMain.frm, as last seen in Step5 AxExe-Threading (using cThreadPool)
    - obviously this project only contains a single Form (fMain) - and nothing else (beside the Dll-reference to 'ThreadedSTAs')
    - also note, that (other than in the AxExes) - the threading will now work also in IDE-mode (with full native compiled speed)

    Step8 Regfree Deployment:
    - And this last step probably goes a long way, to (hopefully) take away some of the "unreasonable fear"...
    (about "Ax-(COM-)Dlls being "hard to deploy", because they "require a setup")
    - VB6-Dlls are wonderful Code-Containers, which run with C-compiled-speed and "describe themselves fully"...
    (because they contain their complete Interface-defs in a Typelib-resource, readable from the outside)
    - Going out of your way, to handle, develop and host "everything in a single Exe", breaks a lot of principles
    of software-engineering ("modularization", "isolated testing", "integration via well-defined interfaces"),
    and is under-using VB6's "COM-Interfaces-the-easy-way"-capabilities...
    - a .\Bin\ or .\Lib\ Folder (shipping "besides your Executable" in your "MyPortableApp.zip") tells the world,
    that you understood (making use of) the concept of "building-blocks in software-development" -> compiled libraries
    - Note, that this Project automatically gathers all Dll-Files from their respective Folders (placing them in ProjectPath\Bin\)
    - ... and what's also automatically ensured (all in IDE-mode only), is the auto-creation of Manifest-Files -> also placed in \Bin\)

    So, what remains, after Step8 was at least "run once" in the IDE (and after having compiled its Std-Executable),
    is to "zip-it-up" for deployment... the Zip should then contain the following Folders and Files:
    \MyApp\ ... (serving as the "root-folder" in your Zip)
    \MyApp\Mandelbrot.exe ... (the Std-Executable, sitting directly in that MyApp-root-folder)
    \MyApp\Bin\ ... (the SubFolder beside your Executable, which contains all Dlls and regfree-Manifests)
    \MyApp\Bin\MandelbrotLib.dll
    \MyApp\Bin\MandelbrotLib.cMandelbrot.manifest
    \MyApp\Bin\ThreadedSTAs.dll
    \MyApp\Bin\ThreadedSTAs.cFactory.manifest

    For the given example, you should end up with a Zip-Deployment-size of about 27KByte for your regfree deployable, portable "threaded VB6-App".

    Threaded-Performance:
    For those interested, whether the "threading was worth it" (and how it "scaled" - performance-wise)...
    Maximizing the StdExe-AppWindow on my machine to "full HD" (1920x1080) I measured:
    - for a single thread (selected in the Combo): 900msec
    - running with 8 threads (via Combo-selection): 135msec
    With "truly linear scaling", the 8-thread-timing should have been: 900/8 ~112msec
    So there's obviously some overhead of 20% or so:
    - due to thread-context-switchery of the system
    - but also because my Intel-CPU has only 6 "real cores" (the other 6 being less-efficient, "hyper-threading-ones")

    Here's hope, that this tutorial is helpful for the community...

    Have fun...

    Edit: Updated TutorialFolder "Step 6..." in the Zip above with the missing typelib 'ThreadAPI.tlb' (as contained in Krools Threadhelper-package)

    Olaf
    Last edited by Schmidt; Feb 28th, 2020 at 02:02 PM.

  2. #2
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by Schmidt View Post
    As the title says - a Tutorial (in 9 Steps - each step in its own Tutorial-Folder),
    which hopefully provides enough help with understanding "the builtin threading-support of VB6"
    (which is entirely based on COM-STAs).

    To describe the tutorial in a short way:
    - in Step0 we start with a normal StdExe-Project - rendering our Mandelbrot from "monolithic code in a *.bas module"
    - ... and finally end up (after Step 8) with a regfree deployable, portable threaded App in a Std-Exe

    Here is the Tutorial-Zip (with its 9 "Step"-Folders and the Tutorial_Readme.txt):
    Attachment 174943

    When you go through the Tutorial-Folders:
    - please don't skip a Step
    - and please compile the Project in each Step (directly into the current Steps Project-Folder)
    - this way, the following steps will find the needed Binaries (Dlls) they depend on

    Ok, here a direct copy of what's contained also in the Tutorial-Readme (describing the 8 Steps in more detail):

    Step0 StdExe (an 'unsplit LongRunner'):
    - trying to cover, what's probably "a typical situation" and where it all starts...
    - the "problem-code" being contained in a "monolithic, straight longrunner-routine"...
    - which "just takes a bit too much time" (especially in the IDE)

    Step1 StdExe (ClassCode in ExeProject):
    - this is perhaps the most important Step to take, since for succesful threading...
    - you'll have to "split the problem" (your monolithic routine) up into "threadable chunks"
    - we do that in a Project-Private Class, ...
    - since we also plan to "move-out" this code (into a separate Dll later)
    - this is where you refine and test your new "chunkable" Routine, until it's solid
    - if your "chunkable worker-routine" has roughly the same speed as the former monolith, all's well

    Step2 Mandel-Dll (move ClassCode):
    - only after you're satisfied with the *stability* of your new Class(Methods), ...
    - should you move the Class-Code into its own Dll-Project (as a now Public Class),
    - to encapsulate it, and to gain perfomance by applying faster native Compiler-settings there
    (whilst your MainExe remains at slower and safer Compiler-settings,... even PCode will do)
    - this Project just needs to be compiled (into the local Project-Folder), to be able to proceed further with Step3 below

    Step3 StdExe (using Mandel-Dll, yet unthreaded):
    - demonstrates, how the StdExe-Project has to be changed and adapted for Dll-Class mode
    - profiting now from better performance (usually about factor 10-20) even in IDE-Mode...
    - and also reducing Code-volume in the Main-Project (faster Startup-Times, faster Intellisense)

    Step4 AxExe-Threading (cThreadHost):
    - shows, how to finally use the compiled Dll(Class) in a scenario with two threads
    - using VB6's already built-in threading support in AxExes (which - as shown - also support InProcess-Threading)
    - cThreadHost is the only Public Class in that AxExe (the one which will load our Dll-Worker-Class on its own Thread)
    - and to overcome the only "quirk" in AxExe-based threading -> the project also contains a small Form (fAsyncHelper.frm)
    - this little helper-form is used within cThreadHost, and provides "async decoupling of method-calls via PostMessage-API"
    - note, how the fMain.frm RedrawMandelBrotArea-routine was changed, compared to the previous example in Step 3:
    - instead "looping the stripes", RedrawMandelBrotArea now only triggers the first stripe on each ThreadHandler
    - the rest of the stripe-calculations will get triggered from within the two ThreadHandler-Events (for TH1 and TH2)

    Step5 AxExe-Threading (cThreadPool):
    - well, the last mentioned point in the descriptions for Step4 above, is the reason for Step5...
    - in Step4 each Thread(HandlerObject) had to be declared WithEvents - each Event then implemented separately
    - so, to avoid that, we introduce a new Class in this Project -> cThreadPool
    - which then allows basically "unlimited cThreadHandlers", providing us with a single Event (for all thread-jobs)
    - this ways the Code in our fMain.frm will get a bit lighter, despite using 3 Threads now
    - note, that cThreadHandler.cls and fAsyncHelper.frm are exact copies from the Step4-project (no changes there)

    Step6 STA-Dll (to support threading, similar to AxExes):
    - Ok, since the goal of this tutorial is, to finally show "regfree deployment of a threaded VB6-solution"...
    - this second Dll-Project will help us to achieve this goal, by providing AxExe-compatible STA-threading for StdExes
    - the AxExe-Project (from previous Step5) already tried to provide its threading support generically by:
    - using the two Classes cThreadHandler and cThreadPool in a way, to load "a secondary worker-dll" (MandelbrotLib.dll)
    - so, these two Classes are also contained in this Dll-Project (slightly changed, but offering similar functionality)
    - also this Dll-Project just needs to be compiled (into the local Project-Folder), to be able to proceed with Step7 below

    Step7 StdExe (using STA-Dll):
    - Well, we're nearly there ... this StdExe-Project is using the above ThreadedSTAs.dll -
    - to provide roughly similar Threading-support in our fMain.frm, as last seen in Step5 AxExe-Threading (using cThreadPool)
    - obviously this project only contains a single Form (fMain) - and nothing else (beside the Dll-reference to 'ThreadedSTAs')
    - also note, that (other than in the AxExes) - the threading will now work also in IDE-mode (with full native compiled speed)

    Step8 Regfree Deployment:
    - And this last step probably goes a long way, to (hopefully) take away some of the "unreasonable fear"...
    (about "Ax-(COM-)Dlls being "hard to deploy", because they "require a setup")
    - VB6-Dlls are wonderful Code-Containers, which run with C-compiled-speed and "describe themselves fully"...
    (because they contain their complete Interface-defs in a Typelib-resource, readable from the outside)
    - Going out of your way, to handle, develop and host "everything in a single Exe", breaks a lot of principles
    of software-engineering ("modularization", "isolated testing", "integration via well-defined interfaces"),
    and is under-using VB6's "COM-Interfaces-the-easy-way"-capabilities...
    - a .\Bin\ or .\Lib\ Folder (shipping "besides your Executable" in your "MyPortableApp.zip") tells the world,
    that you understood (making use of) the concept of "building-blocks in software-development" -> compiled libraries
    - Note, that this Project automatically gathers all Dll-Files from their respective Folders (placing them in ProjectPath\Bin\)
    - ... and what's also automatically ensured (all in IDE-mode only), is the auto-creation of Manifest-Files -> also placed in \Bin\)

    So, what remains, after Step8 was at least "run once" in the IDE (and after having compiled its Std-Executable),
    is to "zip-it-up" for deployment... the Zip should then contain the following Folders and Files:
    \MyApp\ ... (serving as the "root-folder" in your Zip)
    \MyApp\Mandelbrot.exe ... (the Std-Executable, sitting directly in that MyApp-root-folder)
    \MyApp\Bin\ ... (the SubFolder beside your Executable, which contains all Dlls and regfree-Manifests)
    \MyApp\Bin\MandelbrotLib.dll
    \MyApp\Bin\MandelbrotLib.cMandelbrot.manifest
    \MyApp\Bin\ThreadedSTAs.dll
    \MyApp\Bin\ThreadedSTAs.cFactory.manifest

    For the given example, you should end up with a Zip-Deployment-size of about 27KByte for your regfree deployable, portable "threaded VB6-App".

    Threaded-Performance:
    For those interested, whether the "threading was worth it" (and how it "scaled" - performance-wise)...
    Maximizing the StdExe-AppWindow on my machine to "full HD" (1920x1080) I measured:
    - for a single thread (selected in the Combo): 900msec
    - running with 8 threads (via Combo-selection): 135msec
    With "truly linear scaling", the 8-thread-timing should have been: 900/8 ~112msec
    So there's obviously some overhead of 20% or so:
    - due to thread-context-switchery of the system
    - but also because my Intel-CPU has only 6 "real cores" (the other 6 being less-efficient, "hyper-threading-ones")

    Here's hope, that this tutorial is helpful for the community...

    Have fun...

    Olaf

    Dear olaf,

    Thankyou for the samples.
    While going thru the samples I could finish projects upto step 5.
    In step 6 (Step6 STA-Dll (to support threading, similar to AxExes) when I try to build the ThreadedSTAs.dll I get
    ThreadAPI library missing.
    error.
    Please provide the missing files so that I can complete all the 8 steps and try to use the samples.

    regards,
    JSVenu

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    While going thru the samples I could finish projects upto step 5.
    In step 6 (Step6 STA-Dll (to support threading, similar to AxExes) when I try to build the ThreadedSTAs.dll I get
    ThreadAPI library missing.
    error.
    Please provide the missing files so that I can complete all the 8 steps and try to use the samples.
    Ah, sorry - forgot to include Krools 'ThreadAPI.tlb' (which is needed for Dll-compilation in Step 6 of the tutorial).

    Re-uploaded the whole Tutorial-Zip, which now includes this typelib in the "Step6-Folder".

    Olaf

  4. #4
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by Schmidt View Post
    Ah, sorry - forgot to include Krools 'ThreadAPI.tlb' (which is needed for Dll-compilation in Step 6 of the tutorial).

    Re-uploaded the whole Tutorial-Zip, which now includes this typelib in the "Step6-Folder".

    Olaf
    Dear Olaf,

    Thankyou for the updated samples.
    Can you show me how to implement the code http://www.vbforums.com/attachment.p...5&d=1580925327 which you showed using activex exe(AxThreading2 project) and activex dll(MyForms project) contained in _Debug project group using _Step7 StdExe (using STA-Dll) of VB6 Threading-Tutorial (Mandelbrot-Rendering) ie., using std exe and activex dll.

    regards,
    JSVenu

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    Can you show me how to implement the code...
    using activex exe(AxThreading2 project) and activex dll(MyForms project) contained in _Debug project group using _Step7 StdExe (using STA-Dll) of VB6 Threading-Tutorial (Mandelbrot-Rendering) ie., using std exe and activex dll.
    So you're still going on with your "all kind of Forms in Threads" requirement, I guess ...

    This is quite unusual - because normally, you use threads to do "other workload, which is independent from any GUI-stuff"
    (the GUI is normally hosted entirely in the Main-Thread, and only updated with the "results from your worker-threads").

    The only thing GUI-related, which I've occassionally shown on its own thread, is some kind of "Progress- or Splash-Popup-Form".

    So, the examle below will show another "WorkerDll-implementation", which in this case does not "calculate Mandelbrot-Sets",
    but simulates "other WorkLoad", which can then be triggered by:
    - either a "DoWork(...)" Method (which will do the Job without any visible GUI-stuff)
    - or alternatively via a "DoWorkWithProgressForm(...)"-method,
    which does the same things as the DoWork-method, but shows a threaded Progress-Form in addition (at the right side of the screen).

    This optional (threaded) ProgressForm fullfills your requirement, of "dynamically loading a WorkerDll-internally defined UserControl" (ucProgress.ctl).

    Here is a Demo-Zip (which requires, that you've successfully compiled the ThreadedSTAs.dll from Step6 of the Tutorial).

    ThreadFormInDll.zip

    Please compile the Workerlib-Dll first, before running the little Test-App...

    HTH

    Olaf

  6. #6
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    Thankyou very much for the ThreadFormInDll.zip example which is similar to AxThreading2 project activex exe project.


    If you can provide a way to implement your previous simple activex exe
    AxThreading(without user control) example and the threaded form being in the same project as you have shown at link http://www.vbforums.com/attachment.p...3&d=1579859872 as ThreadFormInSameExe.zip
    using _Step7 StdExe (using STA-Dll) of VB6 Threading-Tutorial (Mandelbrot-Rendering) ie., using std exe and activex dll it will be perfect.( If required the user control can be loaded from externalcontrol project at design time like you did in AxThreading project)


    regards,
    JSVenu
    Last edited by jsvenu; Mar 1st, 2020 at 09:12 AM.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    If you can provide a way to implement your previous simple activex exe
    ... as ThreadFormInSameExe.zip
    In case you mean that literally (that the threaded Form shall sit in the StdExe) - this would break "the rule" of:
    - All your threading-code has to sit in a Project-Type that offers Public Classes (e.g. AxExe- and AxDll-ProjectTypes offer that)

    This rule means, that your threadform has to be placed in an AxDll (in case you want to use it from a StdExe).

    Quote Originally Posted by jsvenu View Post
    ...If required the user control can be loaded from externalcontrol project at design time like you did in AxThreading project.
    Hmm, if that's the only thing you're concerned about ...
    (that your Threaded-Form shall be able to create externally encapsulated Controls from OCXes),
    then I don't need to write an "extra-example", because the last Demo I've posted in #5 here,
    can be easily adapted, to show that such "dynamic Ctl-creation from OCXes" works as it should.

    E.g. if you have a recent version 1.6 of Krools VBCCR16-OCX installed and registered on your dev-machine
    (downloadable in precompiled format, from his CommonControl-replacement-project)

    Then you will only have to change two Code-lines within the WorkerLib-Dll Projects fProgress.frm,
    to switch from local loading of "WorkerLib.ucProgress" to external loading of "VBCCR16.ProgressBar":

    In the Form_Load() event-handler:
    Code:
    '  Set ctlProgr = Controls.Add("WorkerLib.ucProgress", "ctlProgr", picTopCont)
      Set ctlProgr = Controls.Add("VBCCR16.ProgressBar", "ctlProgr", picTopCont)
    And in the Worker_Progress(...) event-handler:
    Code:
    '  ctlProgr.Object.SetProgress Perc '<- the .Object-indirection, because of the dynamic hosting in a vbControlExtender
      ctlProgr.Object.Value = 100 * Perc '<- the .Object-indirection, because of the dynamic hosting in a vbControlExtender
    Recompile that Workerlib-dll and that's it.

    HTH

    Olaf

  8. #8
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by Schmidt View Post
    In case you mean that literally (that the threaded Form shall sit in the StdExe) - this would break "the rule" of:
    - All your threading-code has to sit in a Project-Type that offers Public Classes (e.g. AxExe- and AxDll-ProjectTypes offer that)

    This rule means, that your threadform has to be placed in an AxDll (in case you want to use it from a StdExe).



    Hmm, if that's the only thing you're concerned about ...
    (that your Threaded-Form shall be able to create externally encapsulated Controls from OCXes),
    then I don't need to write an "extra-example", because the last Demo I've posted in #5 here,
    can be easily adapted, to show that such "dynamic Ctl-creation from OCXes" works as it should.

    E.g. if you have a recent version 1.6 of Krools VBCCR16-OCX installed and registered on your dev-machine
    (downloadable in precompiled format, from his CommonControl-replacement-project)

    Then you will only have to change two Code-lines within the WorkerLib-Dll Projects fProgress.frm,
    to switch from local loading of "WorkerLib.ucProgress" to external loading of "VBCCR16.ProgressBar":

    In the Form_Load() event-handler:
    Code:
    '  Set ctlProgr = Controls.Add("WorkerLib.ucProgress", "ctlProgr", picTopCont)
      Set ctlProgr = Controls.Add("VBCCR16.ProgressBar", "ctlProgr", picTopCont)
    And in the Worker_Progress(...) event-handler:
    Code:
    '  ctlProgr.Object.SetProgress Perc '<- the .Object-indirection, because of the dynamic hosting in a vbControlExtender
      ctlProgr.Object.Value = 100 * Perc '<- the .Object-indirection, because of the dynamic hosting in a vbControlExtender
    Recompile that Workerlib-dll and that's it.

    HTH

    Olaf
    Dear Olaf,

    Thankyou for the reply.

    In Axthreading project you are displaying Threaded form of same exe in new thread.

    Your AxThreading example contains two form templates frmMain and fThreaded(similar to fProgress form containing progress bar in workerlib activex dll).

    I was just asking for ThreadFormofsameexeInDll.zip which is nothing but the progress bar control containing form fProgress existing in same exe itself instead of in

    workerlib project
    and displaying new object of same fProgress in new thread in workerlib activex dll.(The progress bar can be added to fProgress at design time if not

    possible at runtime) ie., Can the fProgress form template be moved from workerlib actx dll project to _TestWorkerLib std exe project and its object is created in DoWorkWithProgressForm of cWorker class of workerlib actx dll project.If this is possible I think your project can be awesome.Here threading code is in activex dll project only.But the new form object being created and used in new thread by this threading code in activex dll project is from std exe project.

    regards,
    JSVenu
    Last edited by jsvenu; Mar 2nd, 2020 at 02:20 AM.

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    Can the fProgress form template be moved from workerlib actx dll project to _TestWorkerLib std exe project
    and its object is created in DoWorkWithProgressForm of cWorker class of workerlib actx dll project.
    Why would you want to move a threaded-Form from its AxDll-Project (where it belongs) -
    to a StdExe?

    It is perfectly editable and changeable "where it is" (in the AxDll-Project).

    And if you want to develop and debug such a "threadform-in-dll" interactively -
    there's the nice ProjectGroup-feature of the VB6-IDE, which allows exactly that.

    Quote Originally Posted by jsvenu View Post
    Here threading code is in activex dll project only.
    Yes, because isolating "everything which later runs on a thread" within a Dll-Project,
    is the only stable way to do threading (in conjunction with StdExes).

    Quote Originally Posted by jsvenu View Post
    But the new form object being created and used in new thread by this threading code in activex dll project is from std exe project.
    Again, why?

    I see no "practical reason" for that request - if you have one - please tell us about it.

    The only reason I can think of, why someone would want to "drag a StdExe-defined Form into a different Thread",
    is for "malicious intents" (e.g. hijacking a StdExe-defined Login-DialogForm by injecting a Thread into that Vb6 StdExe-Process).

    Again, there is ProjectGroups in VB6, where you can put StdExe-(Test)Projects together with (multiple) Dll- and OCX-Projects for Debugging-purposes.

    And just in case you mean "Template" literally - (and just want to be able to construct "dynamic Forms") -
    there's several examples here in this Forum:
    - how to parse "normal *.frm File-Templates" (which one could store as FrmTemplate-Text also in a DB for example)
    - then (at load-time) looping over all Control-Def-Sections this "Form-Text" contains
    - constructing new Controls (via Controls.Add) on the fly ...
    - on your own (priorily empty) MyDynamicForm-Object

    That's not rocket-science.

    Olaf

  10. #10
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    The only reason I can think of, why someone would want to "drag a StdExe-defined Form into a different Thread",
    is for "malicious intents" (e.g. hijacking a StdExe-defined Login-DialogForm by injecting a Thread into that Vb6 StdExe-Process).
    Dear Olaf,

    You have already given simple example of this type of threading in VB6ThreadingDirectCOM.zip at http://www.vbforums.com/attachment.p...5&d=1432328290

    If hijacking had to be done I can directly hijack any StdExe-Process using my knowledge of vc++ 6.0 win32 unmanaged coding directly without even using vb6 itself.
    The only reason I have is I can create worker threads as well as user interface threads in win32 vc++ 6.0 and even better using MFC.The same I wanted to do in vb6
    but as you told I see threading code in activex dll using CreateThread api.

    Any activex dll can access its loaded exe instance from which it can access and create the form object
    of the exe in new thread and use it like your fProgress.

    I was not asking for already created form object of exe but rather creating a new form object of exe in new thread of activex dll in which the activex dll is loaded.
    Here no callbacks and hijacking.

    regards,
    JSVenu
    Last edited by jsvenu; Mar 3rd, 2020 at 05:27 AM.

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    You have already given simple example of this type of threading in VB6ThreadingDirectCOM.zip
    No, the DirectCOM.dll based example you linked to, follows the exact same rules,
    as the StdExe-based examples I've provided in this Codebank-thread.

    1) No threading-code is run in the StdExe-Project itself
    2) the Threading-Code sits in a separate Dll-Project ...
    ... MandelbrotLib.dll for the Tutorial-Demo,
    ... Workerlib.dll for the ThreadForm-Demo in #5,
    ... and ThreadLib.dll for the DirectCOM-based example you just linked to
    3) the STA-WorkerObject-instance of the above Dll-Projects is in all cases established via a separate Binary
    ... ThreadedSTAs.dll (for all StdExe-based examples in this discussion here)
    ... DirectCOM.dll (for the example you just linked to)

    Quote Originally Posted by jsvenu View Post
    If hijacking had to be done I can directly hijack any StdExe-Process
    using my knowledge of vc++ 6.0 win32 unmanaged coding directly without even using vb6 itself.
    Oh, really?
    I'm relieved, I think...

    But then, if your "vc++ hacking-fu" is that great, why do you ask all these threading-beginner-questions in a VB6-forum?

    Quote Originally Posted by jsvenu View Post
    The only reason I have is I can create worker threads as well as user interface threads in win32 vc++ 6.0...
    The same I wanted to do in vb6
    And I've given you several examples already, how to do "threads with userinterfaces" in VB6.
    So, VB6 can accomplish the exact same things as vc++ (just with other, easier means).

    And one of the VB6-requirements is, that your thread-code sits in a Dll (if you want to use StdExes, and not AxExes).

    Quote Originally Posted by jsvenu View Post
    Any activex dll can access its loaded exe instance from which it can access and create the form object
    of the exe in new thread and use it like your fProgress.
    No, not possible in VB6 (not without hacking the vbRuntime) ... and besides, also not needed.

    Quote Originally Posted by jsvenu View Post
    I was not asking for already created form object of exe
    but rather creating a new form object of exe in new thread of activex dll in which the activex dll is loaded.
    I hear you loud and clear (since you're asking this very same question for about a year now).
    And I take it, that this is possible via vc++...

    But also in a VC++ forum, I'd aks you the same thing:
    Despite being possible, why would you want to do that?

    In case you still don't get what I mean:
    It's perfectly possible, to "shoot yourself in the foot" - but why would anybody want to do that?

    I really cannot see any scenario, where "loading Exe-defined Forms into a Dll" would be an advantage.

    If you want "more dynamics" (more "GUI-flexibility") in your App (your compiled Exe),
    then such scenarios are usually covered by "changeable, or addable Plugins".

    And such Plugins usually come compiled in a *.dll-binary (not in *.exe binaries).
    If you're clever about it, you can switch to new versions, or additions of such "GUI-Plugin-Dlls",
    without even closing your running Exe-instance...
    (which can remain a small, constant "base-binary", without any need to recompile it from your StdExe-Project).

    E.g. at the place where I work, we have this large VB6-based solution (deployment-size ~160MB zipped),
    - which consists of about 10-15 *.exe Files (all relatively small, about 100kB on average)
    - about 100 Dlls (a mix of "flat-dlls" and our own Ax-Dlls)
    - and about 50 OCXes (~90% of them our own)
    All the dependencies are loaded regfree into the Executables.

    And the compile-date on most of the *.exe Files is already "several years in the past".
    So, all the necessary GUI-updates our customers requested, were happening in the Dlls and OCXes, never in the Executables.

    I hope you see better now (before that just mentioned and well working background),
    why I have problems to see any advantage in your request...

    So, unless you provide me with a "very good reason" regarding the "why" of your request,
    I will not answer it (nor will I provide "code for it", because it's "borderline hacky").

    Despite that, I've basically answered it already ...
    (by telling you, to simply parse the "VB6-Form-template" - the *.frm-File - from within your Dll)

    Olaf
    Last edited by Schmidt; Mar 3rd, 2020 at 06:30 AM.

  12. #12
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by Schmidt View Post
    E.g. at the place where I work, we have this large VB6-based solution (deployment-size ~160MB zipped),
    - which consists of about 10-15 *.exe Files (all relatively small, about 100kB on average)
    - about 100 Dlls (a mix of "flat-dlls" and our own Ax-Dlls)
    - and about 50 OCXes (~90% of them our own)
    All the dependencies are loaded regfree into the Executables.

    And the compile-date on most of the *.exe Files is already "several years in the past".
    So, all the necessary GUI-updates our customers requested, were happening in the Dlls and OCXes, never in the Executables.
    Your customers are the luckiest customers in the world. If the deployment-size of your large VB6-based solution is about 160MB zipped, then if other companies want to complete similar features, it may take 2~3GB zipped.

    All over the world,there should be very few VB6-based solutions that are so large and working well, and able to handle modern needs (web apps and mobile apps). At present, it seems that only your solution can fulfill all the requirements of users.

    How wonderful it would be if there were no .NET in this world. LOL.
    Last edited by dreammanor; Mar 4th, 2020 at 10:38 PM.

  13. #13
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    Thankyou for the reply.

    regards,
    JSVenu

  14. #14
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    I have done a multithreadinging application using vbheader using Trick's Multithreading module which works perfect even with pcode for ThreadClient std exe.It basically displays exe form in new thread of activex dll when ever Create exe form object in new thread from dll caption button is clicked on default displayed form of ThreadClient Standard exe project in which we load FormCreator activex dll project thru project references.

    Here no callbacks are used and total multithreading code is shifted to activex dll.
    Just we have to compile and generate FormCreator.dll and include it in ThreadClient standard exe thru project references and create ThreadClient.exe and run it in compiled mode( outside IDE).

    regards,
    JSVenu
    Attached Files Attached Files
    Last edited by jsvenu; Mar 16th, 2020 at 08:27 AM.

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    I have done a multithreadinging application using vbheader using
    Nope, that's not a multithreading-application (it neither does anything useful, nor does it have the potential to do so).

    Also note, that the Dll does not run on its own thread - and was compiled "single-threaded" (which limits its usefulness).

    So far, this is the classic scenario of: "solution, in desperate need for a problem".

    You've still not shown, what problem the whole thing is supposed to solve (when it's finally ready)...

    Olaf

  16. #16
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by Schmidt View Post
    Nope, that's not a multithreading-application (it neither does anything useful, nor does it have the potential to do so).

    Also note, that the Dll does not run on its own thread - and was compiled "single-threaded" (which limits its usefulness).

    So far, this is the classic scenario of: "solution, in desperate need for a problem".

    You've still not shown, what problem the whole thing is supposed to solve (when it's finally ready)...

    Olaf
    Dear Olaf,

    First thankyou very much for the reply.

    For only my understanding please clarify me the following four points:

    Point 1:

    What are the things which an activex dll cannot do when it is compiled single threaded.What is the limitation here.

    Suppose in the example ThreadFormInDll which you provided we set the threading model of WorkerLib activex dll to Single Threaded.Then also it is working fine.Can you please tell me what will be its limitation when it is not Apartment Threaded.What are the advantages it will have when it is apartment threaded.


    Point 2:

    If I use vbheader along with multithreading module in ThreadSingle standard exe I can display new Form of exe in new thread of dll by setting dll threading model as Apartment Threaded only since it does not work giving Run-time error '-2147467259 (80004005)': Automation error if I set dll threading model to Single Threaded. Why.


    Point 3:

    If at all I use vbheader along with multithreading module only in a standard exe and display new Form of exe in new thread in same exe itself everything is perfect.Then what is the need for activex dll irrespective of Threading model.But here the standard exe does not support pcode.


    Point 4:

    Finally Why this pcode compiling is required.Is there any advantage of using it in different types of vb6 projects ( actx dll,standard exe,actx exe,actx control).


    regards,

    JSVenu

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    First thankyou very much for the reply.
    These over-polite greetings will only get you "so far" - especially when they are paired with:
    "outright ignorance of everything your dialog-partner suggested, or asked you" (repeatedly).

    Quote Originally Posted by jsvenu View Post
    For only my understanding please clarify me the following four points:
    Really - why should I?
    I think it's you who should answer my questions first (which have accumulated to quite an amount).

    Despite of that, everything you asked was basically already answered in earlier threads and replies,
    with the one exception of "what are Single-Threaded compiled Dlls good for"?

    Short answer: they are there for compatibility-reasons (to be combinable with other, older - also
    singlethreaded-compiled binaries ... e.g. there's certain older OCXes which come with that threading-model).

    Longer answer:
    Single-threaded compiled binaries are flagged with "ThreadingModel: None" -
    they were intended to "only run support in a given GUIs mainthread" - and will make problems (are rejected),
    when you want to combine them with binaries which were differently compiled (threading-model wise).
    (e.g. in ThreadPool-Hosts like MS-COM+ or the (Web-)App-pools of the MS-Webserver IIS).

    So, recommended is, to use the pre-set default in AX-Dll-projects (ThreadingModel: Apartment),
    because this type has a much broader range of "combinability" (or "Pool-hostability")...

    Olaf

  18. #18
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    Dear Olaf,

    First thankyou very much for the reply.

    For only my understanding please clarify me the following four points:

    Point 1:

    What are the things which an activex dll cannot do when it is compiled single threaded.What is the limitation here.

    Suppose in the example ThreadFormInDll which you provided we set the threading model of WorkerLib activex dll to Single Threaded.Then also it is working fine.Can you please tell me what will be its limitation when it is not Apartment Threaded.What are the advantages it will have when it is apartment threaded.


    Point 2:

    If I use vbheader along with multithreading module in ThreadSingle standard exe I can display new Form of exe in new thread of dll by setting dll threading model as Apartment Threaded only since it does not work giving Run-time error '-2147467259 (80004005)': Automation error if I set dll threading model to Single Threaded. Why.


    Point 3:

    If at all I use vbheader along with multithreading module only in a standard exe and display new Form of exe in new thread in same exe itself everything is perfect.Then what is the need for activex dll irrespective of Threading model.But here the standard exe does not support pcode.


    Point 4:

    Finally Why this pcode compiling is required.Is there any advantage of using it in different types of vb6 projects ( actx dll,standard exe,actx exe,actx control).


    regards,

    JSVenu
    Dear Olaf,

    I got the Run-time error '-2147467259 (80004005)': Automation error in Point 2 solved just by properly compiling and including the activex dll to standard exe thru project references and I am able to use standard exe with vbheader along with activex dll set to either Single Threaded or Apartment thread.

    As per your clarification I use activex dll set to Apartment model.
    Here again our activex dll supports pcode.But our Standard exe is not supporting pcode.
    But overall task is achieved.

    regards,
    JSVenu

  19. #19
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    When we run _TestWorkerLib.exe of std exe project of ThreadFormInDll with WorkerLib activex dll object set to Single Threaded threading model a form with "ThreadPool with 0 Threads" in its Caption is displayed .

    Here can you clarify why this error occurs and how we can catch the error and display a msgbox about this zero thread entries before displaying the form since the standard exe project (_TestWorkerLib)interacts with two activex dll projects(ThreadedSTAs and WorkerLib).

    regards,
    JSVenu

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    When we run _TestWorkerLib.exe of std exe project of ThreadFormInDll
    with WorkerLib activex dll object set to Single Threaded threading model ...
    I thought I already wrote, that Thread-Workerlibs which later are planned to be "run on STAs",
    should be left at their defaults ("ThreadingModel-Apartment").

    So the ThreadPool-Object behaves absolutely correct,
    when it denies the instancing of ThreadObjects from Ax-Worker-Dlls which were flagged "Single Threaded".
    (finally resulting in a ThreadPool-Count of Zero).

    Again, it is possible to cover 99% of all threadig-scenarios with VB6 (in a safe and stable way) -
    when you just follow these simple rules:
    - implement your Code (which later runs threaded) in a Public Class in a VB6-AxDll (your "Worker-Dll")
    - if you want Forms on your Worker-Threads, then place the Form-definition-files inside the Worker-Dll-Project

    That's all there is basically ...
    (in other words: "stick to the rules of STA-threading" - which is the only model VB6 supports in a stable manner)

    Perhaps a few "don'ts" are needed in addition...:
    - don't change the Worker-AxDll-Project from its ThreadingModel default-settings ("Apartment Threaded") to "Single Threaded"
    - don't use any "hacks" (like the vbRuntime-hacks) in your hosting StdExe-Project
    - don't use any "additional hacks" in the Worker-AxDll-Project either
    Because that's your UserCode-Projects (the Worker-Dll and your StdExe)...
    they should remain "pristine" (VB6-code wise, for stable operation).

    Olaf

  21. #21
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    Ok. Now having explained why , can you clarify me how to catch the error before in the following code of ThreadSTA.dll for cThreadHost class CreateWorkerObject function shown below for the line

    If CT.State < 0 Then Err.Raise vbObjectError, , IIf(CT.State = -1, "Object-Creation failed", "Proxy/Stub-Creation failed")

    like thru a msgbox or an event :



    Code:
    Public Function CreateWorkerObject(ProgID As String, Optional ManifestPath As String, Optional ByVal TimeOutHardTerminateMSec& = 1000) As Object
      mTimeOutHardTerminateMSec = TimeOutHardTerminateMSec
      CT.IID_IUnk.Data4(0) = &HC0: CT.IID_IUnk.Data4(7) = &H46
      CT.Cls_ID = FactClsID
      CT.ProgID = ProgID
      CT.ManifestPath = ManifestPath
      CT.State = 0: CT.pStream = 0
      CT.pStreamT = CoMarshalInterThreadInterfaceInStream(CT.IID_IUnk, Me)
      CT.hThread = CreateThread(0, 0, AddressOf ThreadProc, VarPtr(CT), 0, CT.ThreadID)
      
      Dim i As Long
      For i = 1 To 100 'wait about a second (max), for the ThreadObject to "come online"
        Sleep 12: If CT.State <> 0 Or CT.pStream <> 0 Then Exit For
      Next
      
      If CT.pStream Then Set mWorker = CoGetInterfaceAndReleaseStream(CT.pStream, CT.IID_IUnk)
      If CT.State < 0 Then Err.Raise vbObjectError, , IIf(CT.State = -1, "Object-Creation failed", "Proxy/Stub-Creation failed")
      Set CreateWorkerObject = mWorker
    End Function
    regards,
    JSVenu

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,924

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Quote Originally Posted by jsvenu View Post
    ...can you clarify me how to catch the error before in the following code of ThreadSTA.dll for cThreadHost class CreateWorkerObject function shown below for the line

    If CT.State < 0 Then Err.Raise vbObjectError, , IIf(CT.State = -1, "Object-Creation failed", "Proxy/Stub-Creation failed")

    like thru a msgbox or an event :
    You can do that in your UserCode (without changing anything in the ThreadSTA.dll-Project) -
    via explicit testing of the return-value (which should be the marshaled ProxyObj-instance)

    Code:
      Dim i 'let's add 4 WorkerObjects to the ThreadPool (using their predefined ProgID-Const)
      For i = 1 To 4
        If TP.AddWorkerThreadObject(ProgID_WorkObj) Is Nothing Then _
              MsgBox "didn't get a Proxy-instance for: " & ProgID_WorkObj: Exit For
      Next
    But if you prefer the handling of a "raised, hard error" from within the ThreadSTA.dll -
    then you could add the following as the last line in the cThreadHost.CreateWorkerObject Function:
    Code:
       If mWorker Is Nothing Then Err.Raise vbObjectError, , "Proxy/Stub-Creation incomplete"
    Olaf

  23. #23
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    335

    Re: VB6 Threading-Tutorial (Mandelbrot-Rendering)

    Dear Olaf,

    Understood.

    regards,
    JSVenu

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width