Page 1 of 2 12 LastLast
Results 1 to 40 of 42

Thread: The easiest way of multithreading

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Arrow The easiest way of multithreading

    I've found this example, but I still don't understand it quite well because it's not commented, so I don't have a clue how to interact with the each thread and terminate all of them when I want to stop the process by closing the program or clicking on some "Stop" button. I don't want to do the creation of the external process or to call external file (DLL/EXE) or to use some complex classes/hacks, all I want is a simple multithreading which is almost ideal to the example that's mentioned above. Is that achievable i.e. is that project fixable or it has some flaws that can't be easily resolved?
    My goal is to create asynchronous operations (timers) which will not freeze the UI - so the threading will be the solution.
    Last edited by MikiSoft; Apr 5th, 2015 at 12:08 PM.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: The most easiest way of multithreading

    Simple Multithreading with VB6 would be considered an oxymoron

    If you don't want to use an ActiveX EXE then throw away the word simple. Though not sure multithreading + VB6 can ever be termed simple. Any other method may require an external DLL and/or some serious hacks.

    From the link you posted and the comments therein, doesn't that project create additional processes vs. threads?

    If multithreading with VB6 was simple, you'd find 10s of thousands of examples posted all over the web. Wish it was easy.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: The most easiest way of multithreading

    Quote Originally Posted by LaVolpe View Post
    Simple Multithreading with VB6 would be considered an oxymoron

    If you don't want to use an ActiveX EXE then throw away the word simple. Though not sure multithreading + VB6 can ever be termed simple. Any other method may require an external DLL and/or some serious hacks.

    From the link you posted and the comments therein, doesn't that project create additional processes vs. threads?

    If multithreading with VB6 was simple, you'd find 10s of thousands of examples posted all over the web. Wish it was easy.
    I know that it's not simple, but that man did it a lot simpler than all examples that I've found.
    I didn't linked to the main post, I've linked to the comment in that topic where is attached another project which I'm talking about.
    Last edited by MikiSoft; Apr 4th, 2015 at 03:48 PM.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: The most easiest way of multithreading

    Okay, here it is. Solid as rock with minimal code and hacking
    BTW. I saw that this self-hosted ActiveX EXE approach was also presented by Olaf (Schmidt), but I didn't understood his code because it was created to calculate and draw fractals, so it was pretty complicated.

    UPDATED #2:
    Attached Files Attached Files
    Last edited by MikiSoft; Dec 8th, 2015 at 11:08 PM.

  6. #6
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: The most easiest way of multithreading

    Hello MikiSoft. Specially for you I made this example. This is the usual project - StandartEXE. Take here the type library and read the description. Quite simply, instead of CreateThread are using vbCreateThread. Thread draws fractal. The main thread is used for the GUI.
    Form:
    Code:
    Option Explicit
    
    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    Private Declare Function ColorHLSToRGB Lib "shlwapi.dll" (ByVal wHue As Integer, ByVal wLuminance As Integer, ByVal wSaturation As Integer) As Long
    
    Dim hThread As Long
    Dim di      As Single
    Dim dr      As Single
    Dim re      As Single
    Dim ie      As Single
    
    Private Sub Form_Load()
        Dim i   As Long
        
        ' Create palette
        For i = 0 To 99
            SimpleMultithreading.Palette(i) = ColorHLSToRGB(i * 2.42, 120, 240)
        Next
        
        ' Set viewport
        iLeft = -1
        iRight = 1
        iTop = -1
        iBottom = 1
        
        Randomize
        
        ' Set finish value
        re = Rnd * 2 - 1
        ie = Rnd * 2 - 1
        dr = (re - Real) / 40
        di = (ie - Imaginary) / 40
        
        Process = True
        ' Call function in a new thread
        hThread = vbCreateThread(0, 0, AddressOf DrawJulia, ObjPtr(picDisp), 0, 0)
        
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Process = False
        ' Wait until thread ends
        WaitForSingleObject hThread, -1
    End Sub
    
    Private Sub tmrFPS_Timer()
        Me.Caption = Format(FPS, "\F\P\S 0")
        FPS = 0
    End Sub
    
    Private Sub tmrInterpolation_Timer()
        
        ' Interpolation
        Real = Real + dr
        Imaginary = Imaginary + di
        
        If Abs(Real - re) < 0.0001 Then re = Rnd * 2 - 1: dr = (re - Real) / 40
        If Abs(Imaginary - ie) < 0.0001 Then ie = Rnd * 2 - 1: di = (ie - Imaginary) / 40
        
    End Sub
    Module:
    Code:
    Option Explicit
    
    Public Type RGBQUAD
        rgbBlue As Byte
        rgbGreen As Byte
        rgbRed As Byte
        rgbReserved As Byte
    End Type
    Public Type BITMAPINFOHEADER
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
    End Type
    Public Type BITMAPINFO
        bmiHeader As BITMAPINFOHEADER
        bmiColors As RGBQUAD
    End Type
    
    Private Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
    Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
    
    Public iLeft        As Double
    Public iTop         As Double
    Public iRight       As Double
    Public iBottom      As Double
    Public Real         As Double
    Public Imaginary    As Double
    Public Process      As Boolean
    Public Palette(99)  As Long
    Public FPS          As Long
    
    ' // Function draw fractal on the picturebox
    Public Function DrawJulia(ByVal pic As PictureBox) As Long
        Dim x As Double, y As Double, Sx As Double, Sy As Double
        Dim pt As Long, Bits() As Long, bi As BITMAPINFO
        Dim lx As Long, ly As Long
              
        ReDim Bits(pic.ScaleWidth * pic.ScaleHeight - 1)
    
        With bi.bmiHeader
            .biBitCount = 32
            .biHeight = -pic.ScaleHeight
            .biWidth = pic.ScaleWidth
            .biPlanes = 1
            .biSize = Len(bi.bmiHeader)
            .biSizeImage = pic.ScaleWidth * pic.ScaleHeight * 4
        End With
          
        Do While Process
        
            Sx = (iRight - iLeft) / (pic.ScaleWidth - 1)
            Sy = (iRight - iLeft) / (pic.ScaleHeight - 1)
            x = iLeft: y = iTop
            
            Process = Not Not Process
            pt = 0
            
            For ly = 0 To pic.ScaleHeight - 1: For lx = 0 To pic.ScaleWidth - 1
                x = x + Sx
                Bits(pt) = Palette(Julia(x, y))
                pt = pt + 1
            Next: y = y + Sy: x = iLeft: Next
        
            SetDIBitsToDevice pic.hdc, 0, 0, pic.ScaleWidth, ly, 0, 0, 0, ly, Bits(0), bi, 0
            
            pic.CurrentX = 0
            pic.CurrentY = 0
            pic.Print Format(GetCurrentThreadId(), "T\hrea\d #")
            
            FPS = FPS + 1
            
        Loop
        
    End Function
    
    ' // Function return value Julia set
    Private Function Julia(x As Double, y As Double) As Single
        Dim Zr As Double, Zi As Double
        Dim Cr As Double, Ci As Double
        Dim tZr As Double
        Dim count As Long
        Dim r As Single
        count = 0
        Zr = x: Zi = y
        Cr = Real: Ci = Imaginary
        Do While count < 99 And r < 10
            tZr = Zr
            Zr = Zr * Zr - Zi * Zi
            Zi = tZr * Zi + Zi * tZr
            Zr = Zr + Cr
            Zi = Zi + Ci
            r = Sqr(Zr * Zr + Zi * Zi)
            count = count + 1
        Loop
        Julia = count
    End Function
    SimpleMultithreading.zip

    UPDATE: Make only a compiled version.

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: [RESOLVED] The most easiest way of multithreading

    Thanks for the effort, but I've already solved my problem with simple approach above. I want to ask why ActiveX EXE is different than Standard EXE as it does not require manual registration process (unlike DLL or OCX)?
    Last edited by MikiSoft; Apr 5th, 2015 at 03:57 PM.

  8. #8

  9. #9
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [RESOLVED] The most easiest way of multithreading

    MikiSoft, you edited your first post to include a goal. Timers should never freeze up the UI. I am assuming you are not talking about the timers, but rather the code that is called/executed once your timer event is received? If that is not the case, maybe we should be asking why your timers are freezing up your UI?
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: [RESOLVED] The most easiest way of multithreading

    @The trick: I see now. That can be a problem, but in almost every project I include ActiveX components so Administrator rights will be definitely needed.

    @LaVople: I'm creating an array of timers to do some operation, so on slower computers they can freeze the UI and slow down each other.

  11. #11

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: The most easiest way of multithreading

    Can that be used for ActiveX EXE or not? If yes, can I have some example? Answer here, thanks.
    Last edited by MikiSoft; Apr 5th, 2015 at 04:23 PM.

  13. #13
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: The most easiest way of multithreading

    Quote Originally Posted by MikiSoft View Post
    Okay, here it is. Solid as rock with minimal code and hacking
    BTW. I saw that this self-hosted ActiveX EXE approach was also presented by Olaf, but I didn't understood his code because it was created to calculate and draw fractals, so it was pretty complicated.

    UPDATED:
    I don't understand what is multi-threading about this. The threads only run one at a time.


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: The most easiest way of multithreading

    You must compile it and run, otherwise in the IDE it won't work.
    Last edited by MikiSoft; Apr 5th, 2015 at 11:45 AM.

  15. #15
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: The most easiest way of multithreading

    Quote Originally Posted by The trick View Post
    Hello MikiSoft. Specially for you I made this example. This is the usual project - StandartEXE. Take here the type library and read the description. Quite simply, instead of CreateThread are using vbCreateThread. Thread draws fractal. The main thread is used for the GUI.
    Form:
    Code:
    Option Explicit
    
    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    Private Declare Function ColorHLSToRGB Lib "shlwapi.dll" (ByVal wHue As Integer, ByVal wLuminance As Integer, ByVal wSaturation As Integer) As Long
    
    Dim hThread As Long
    Dim di      As Single
    Dim dr      As Single
    Dim re      As Single
    Dim ie      As Single
    
    Private Sub Form_Load()
        Dim i   As Long
        
        ' Create palette
        For i = 0 To 99
            SimpleMultithreading.Palette(i) = ColorHLSToRGB(i * 2.42, 120, 240)
        Next
        
        ' Set viewport
        iLeft = -1
        iRight = 1
        iTop = -1
        iBottom = 1
        
        Randomize
        
        ' Set finish value
        re = Rnd * 2 - 1
        ie = Rnd * 2 - 1
        dr = (re - Real) / 40
        di = (ie - Imaginary) / 40
        
        Process = True
        ' Call function in a new thread
        hThread = vbCreateThread(0, 0, AddressOf DrawJulia, ObjPtr(picDisp), 0, 0)
        
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Process = False
        ' Wait until thread ends
        WaitForSingleObject hThread, -1
    End Sub
    
    Private Sub tmrFPS_Timer()
        Me.Caption = Format(FPS, "\F\P\S 0")
        FPS = 0
    End Sub
    
    Private Sub tmrInterpolation_Timer()
        
        ' Interpolation
        Real = Real + dr
        Imaginary = Imaginary + di
        
        If Abs(Real - re) < 0.0001 Then re = Rnd * 2 - 1: dr = (re - Real) / 40
        If Abs(Imaginary - ie) < 0.0001 Then ie = Rnd * 2 - 1: di = (ie - Imaginary) / 40
        
    End Sub
    Module:
    Code:
    Option Explicit
    
    Public Type RGBQUAD
        rgbBlue As Byte
        rgbGreen As Byte
        rgbRed As Byte
        rgbReserved As Byte
    End Type
    Public Type BITMAPINFOHEADER
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
    End Type
    Public Type BITMAPINFO
        bmiHeader As BITMAPINFOHEADER
        bmiColors As RGBQUAD
    End Type
    
    Private Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
    Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
    
    Public iLeft        As Double
    Public iTop         As Double
    Public iRight       As Double
    Public iBottom      As Double
    Public Real         As Double
    Public Imaginary    As Double
    Public Process      As Boolean
    Public Palette(99)  As Long
    Public FPS          As Long
    
    ' // Function draw fractal on the picturebox
    Public Function DrawJulia(ByVal pic As PictureBox) As Long
        Dim x As Double, y As Double, Sx As Double, Sy As Double
        Dim pt As Long, Bits() As Long, bi As BITMAPINFO
        Dim lx As Long, ly As Long
              
        ReDim Bits(pic.ScaleWidth * pic.ScaleHeight - 1)
    
        With bi.bmiHeader
            .biBitCount = 32
            .biHeight = -pic.ScaleHeight
            .biWidth = pic.ScaleWidth
            .biPlanes = 1
            .biSize = Len(bi.bmiHeader)
            .biSizeImage = pic.ScaleWidth * pic.ScaleHeight * 4
        End With
          
        Do While Process
        
            Sx = (iRight - iLeft) / (pic.ScaleWidth - 1)
            Sy = (iRight - iLeft) / (pic.ScaleHeight - 1)
            x = iLeft: y = iTop
            
            Process = Not Not Process
            pt = 0
            
            For ly = 0 To pic.ScaleHeight - 1: For lx = 0 To pic.ScaleWidth - 1
                x = x + Sx
                Bits(pt) = Palette(Julia(x, y))
                pt = pt + 1
            Next: y = y + Sy: x = iLeft: Next
        
            SetDIBitsToDevice pic.hdc, 0, 0, pic.ScaleWidth, ly, 0, 0, 0, ly, Bits(0), bi, 0
            
            pic.CurrentX = 0
            pic.CurrentY = 0
            pic.Print Format(GetCurrentThreadId(), "T\hrea\d #")
            
            FPS = FPS + 1
            
        Loop
        
    End Function
    
    ' // Function return value Julia set
    Private Function Julia(x As Double, y As Double) As Single
        Dim Zr As Double, Zi As Double
        Dim Cr As Double, Ci As Double
        Dim tZr As Double
        Dim count As Long
        Dim r As Single
        count = 0
        Zr = x: Zi = y
        Cr = Real: Ci = Imaginary
        Do While count < 99 And r < 10
            tZr = Zr
            Zr = Zr * Zr - Zi * Zi
            Zi = tZr * Zi + Zi * tZr
            Zr = Zr + Cr
            Zi = Zi + Ci
            r = Sqr(Zr * Zr + Zi * Zi)
            count = count + 1
        Loop
        Julia = count
    End Function
    SimpleMultithreading.zip

    UPDATE: Make only a compiled version.


    Can't find project or library

    tlsIndex = TlsAlloc()


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  16. #16
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: The most easiest way of multithreading

    Quote Originally Posted by MikiSoft View Post
    You must compile it and run, otherwise in the IDE it won't work.
    OK, very nice.


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  17. #17
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: The most easiest way of multithreading

    Quote Originally Posted by jmsrickland View Post
    Can't find project or library
    tlsIndex = TlsAlloc()
    Quote Originally Posted by The trick View Post
    Take here the type library and read the description.
    See type library in the reference thread.
    What sense in this multi-threading? (I mean the ActiveX EXE) DoEvents in a loop many times slow. I understand This is needed to marshalling. Interactions are synchronous, then what meaning in that? If you need to get some sort of response from another thread I should wait.

  18. #18
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,169

    Re: Reg-Free ActiveX EXE, possible?

    @MikiSoft: You don't need reg-free COM activation for your ActiveX EXE if you know beforehand the relative path to this executable once the whole solution is deployed. Then you can just manually start it w/ CreateProcess/ShellExecute and it will automagically register its public class factories w/ CoRegisterClassObject in ROT.

    Unfortunately VB6 out-of-processes servers try to autoregister some marshaling support on start-up and this fails with bizarre errors when the first user to start it is not an admin. So the answer is both yes and no, it cannot be done.

    Here is another strategy that is very hard to be done with VB6.

    cheers,
    </wqw>

  19. #19

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Thanks wqweto for the answer! Has anyone from here tried to accomplish that strategy or something similar, in order to avoid VB6 servers to do the registration process? It really bugs me, even more now when you said that, if I understood correctly, Administrator rights aren't really needed to do the proper registration of the out-of-process COM object.
    Last edited by MikiSoft; Apr 7th, 2015 at 12:31 PM.

  20. #20
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Reg-Free ActiveX EXE, possible?

    Quote Originally Posted by wqweto View Post
    Unfortunately VB6 out-of-processes servers try to autoregister some marshaling support on start-up and this fails with bizarre errors when the first user to start it is not an admin. So the answer is both yes and no, it cannot be done.
    I swear to God, ActiveX could be a real pain that threatens to drive one insane.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  21. #21
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by MikiSoft View Post
    ... if I understood correctly, Administrator rights aren't really needed to do the proper registration of the out-of-process COM object.
    No, you "understood" exactly incorrectly.

    An ActiveX EXE is an out of process COM server, and a VB6 ActiveX EXE merely follows the ActiveX and DCOM specifications, which require self-registration. By their nature the keys must be registered globally, so elevated permission is required. In this context the "first run" can perform the required registration but it must be an elevated run.


    If you really "need multithreading" you might consider whether or not you can use a worker process instead of a worker thread. Of course you'll need to choose an IPC mechanism and deal with synchronization.

    But even then you can't write your "worker" code based on busy loops and blocking calls. If you do, the worker has no way to be responsive to something like a shutdown request from the main program.

    If you take yourself out of that box (busy/blocking code) you may suddenly realize you never needed a worker thread in the first place.

  22. #22
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by dilettante View Post
    An ActiveX EXE is an out of process COM server, ...
    The above line is of course right - but I catched it up, to maybe shift the focus again,
    on what we have here (with regards to, what triggered the OPs question).

    It's InProcess-Threading we talk about (by means of an ActiveX-Exe-Host, which
    of course could also act as an OutOfProcess-Server - but in case of the OP is
    never used in that mode).

    The InProcess-STAs in this AxExe-Mode are created by (Process-internal) calls to
    CreateObject("MyProject.cMyInternalPublicClass"), which (when properly registered)
    will instantiate the ClassObject (according to the ProgID we used in CreateObject)
    on a new STA which runs in the same Process as the CreateObject-Caller.

    When the Object in question would be instantiated instead by: New cMyInternalPublicClass
    then the instance is not being created on a new STA, but on the calling thread instead
    (usually the Main-Thread - aka "normal Class-instantiation/communication").

    Just for completeness (although it was already mentioned in this discussion) - when
    running such an InProcessThreading AxExe-Project in the IDE, the just mentioned
    CreateObject(ThreadClassProgID)-calls will not cause the creation of a new STA -
    instead the behaviour is comparable to using the normal instantiation per New
    (which allows for easier debugging).

    So, we have a quite easy and comfortable way to use InProcess-Threading in VB6 -
    but (as this thread shows) - the only "catch" is the requirement, that the ActiveX-
    Exe in question needs to be registered on the target-machine, to perform its
    InProcess-Threading as designed.

    @the OP
    The reason for that is, that communication among Objects on different STAs has to be
    marshalled - and the systems COM-marshaller cannot make use of the Interface-Infos
    which are already contained in the compiled VB-Executable - only the VB6-AxExe knows
    about them (to be used when "Objects talk among themselves" on the Main-Thread) -
    for transparent cross-STA-communication among Objects these Interface Infos for the
    Proxy/Stub-pairs have to be additionally available in the registry (because that's where
    the marshaller-APIs will search for them).

    There's no easy way around it (with regards to "Setup-free deployment") - other than
    giving the information to the potential User (either in a ReadMe - or in a small Popup-
    Info-Message which is shown on first start) - that the first run of the executable
    has to be done in elevated mode (per "Run as Administrator").

    On subsequent runs this won't be necessary anymore - but it's still a nuisance
    (that's why I do my Thread-stuff not in Public ActiveX-Exe-Classes, but in Public
    Dll-Classes, since that approach allows "regfree instantiation on STAs").

    Olaf

  23. #23

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by Schmidt View Post
    that's why I do my Thread-stuff not in Public ActiveX-Exe-Classes, but in Public
    Dll-Classes, since that approach allows "regfree instantiation on STAs"
    Can you give me some example of that approach which is like my project above, if one could be ever made to be simple like that? Also, thanks for the detailed explanation, I fully understand it now!
    Last edited by MikiSoft; Apr 8th, 2015 at 06:48 AM.

  24. #24
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by MikiSoft View Post
    Can you give me some example of that approach which is like my project above, if one could be ever made to be simple like that?
    The "simplicity" will depend a bit on, whether you want to show Forms from within your Threads -
    or if these Threads are meant as "invisible workers" only...

    Though since you opened yourself up to the idea, to use ActiveX-Dlls
    (relinquishing the "everything in one Exe"-approach), you will now
    have to consider your regfree shipping with an additional \Bin\-Folder
    in your Zip (instead of a zipped "single Exe").

    Basically you now have 3 options (3 convenience-levels, if you want) - though
    each requires at least the ActiveX-Dll which contains your Thread-Class.

    1) - Anatolis (The Trick's) Dll-threading approach without any additional helpers:
    \MyStd.exe
    \..\Bin\MyActiveXThread.dll

    2) - DirectCOM.dll based (DirectCOM.dll adding ~20kB to your Zip-Archives size)
    \MyStd.exe
    \..\Bin\MyActiveXThread.dll
    \..\Bin\DirectCOM.dll

    3) - vbRichClient5 based (RC5-BaseDlls adding ~2.3MB to your Zip-Archives size)
    \MyStd.exe
    \..\Bin\MyActiveXThread.dll
    \..\Bin\DirectCOM.dll
    \..\Bin\vbRichClient5.dll
    \..\Bin\vb_cairo_sqlite.dll

    I've ordered them already according to their comfort-level with regards to
    the threading-implementation - though each of the above is able to cover
    regfree deployment as a "portable App".

    Before I write an example, I'd like to know which of the above modes you'd
    prefer (e.g. if you can live with the RC5-dependency, since that would require
    the least efforts on my end).

    Olaf

  25. #25

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    I would choose the first approach since it's the most comfortable way, and if forms can't be included then they are not needed (the reason I have included them into my project is for better understanding and for showing how it works live). Thanks in advance!
    Last edited by MikiSoft; Apr 8th, 2015 at 07:35 AM.

  26. #26
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by MikiSoft View Post
    I would choose the first approach since it's the most comfortable way,...
    Ehm, to be more clear about that - when I mentioned that I ordered them according to their
    comfort-level, I meant "increased comfort (coding-wise), the further you go down the list".

    To see examples for Tricks approach, you can already take a look here, and see if that suits your needs:
    http://www.vbforums.com/showthread.p...-in-VB6-part-1
    or
    http://www.vbforums.com/showthread.p...-of-Native-DLL

    Olaf

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    The first method with ActiveX DLL seems to be easier but I don't understand how to implement that into my project, it's a sensitive job since it's working directly with CLSIDs and COM API calls. But it will definitely be the best solution for this problem (if it really doesn't need to be run with Administrator privileges).
    Last edited by MikiSoft; Apr 8th, 2015 at 09:42 AM.

  28. #28
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by MikiSoft View Post
    The first method with ActiveX DLL seems to be easier...
    You're kidding right ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  29. #29

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Umm no? Why on the Earth would be a second method easier, since it works with native DLL which can't be made using VB6 without some hacking around...
    Last edited by MikiSoft; Apr 8th, 2015 at 04:34 PM.

  30. #30
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,169

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    I think @trick had a sample of multi-threading with *standard* executable -- no AxEXE, no dlls.

    cheers,
    </wqw>

  31. #31
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Sorry for my bad English.
    Quote Originally Posted by MikiSoft View Post
    The first method with ActiveX DLL seems to be easier but I don't understand how to implement that into my project, it's a sensitive job since it's working directly with CLSIDs and COM API calls.
    You can use the CreateObject. I wrote there.
    Quote Originally Posted by MikiSoft View Post
    Umm no? Why on the Earth would be a second method easier, since it works with native DLL which can't be made using VB6 without some hacking around...
    I created the opportunity multithreading in a standard EXE. This is almost a complete analog CreateThread and _beginthread. Why not use it?

  32. #32

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by The trick View Post
    You can use the CreateObject. I wrote there.
    Can you make a minimalist example using that command? I have now attached my project, splitted into Standard EXE and ActiveX DLL, so you can work with that.
    Attached Files Attached Files
    Last edited by MikiSoft; Apr 10th, 2015 at 04:18 AM.

  33. #33

  34. #34

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Bump - have you done that? I want my project above to be modified so I would know the differences and better understand it.
    Last edited by MikiSoft; Apr 11th, 2015 at 04:44 PM.

  35. #35

  36. #36
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    So this thread's question was actually resolved back in post #4.

    Sounds like everything else should have been split off and moved back to the original thread.

  37. #37

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Quote Originally Posted by dilettante View Post
    So this thread's question was actually resolved back in post #4.

    Sounds like everything else should have been split off and moved back to the original thread.
    I was thinking the same, it need to be reported to moderators.

    Quote Originally Posted by The trick View Post
    Wait for the response on Monday, as I do not have access to a computer (I'm writing from the phone)
    OK, I'll wait.
    Last edited by MikiSoft; Apr 11th, 2015 at 04:44 PM.

  38. #38
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Hello. As I promised (slightly delayed).
    The first example - using multi-threading ActiveX DLL.
    Create a new project ActiveX DLL. Create a new class Thread.cls.
    Code:
    Public Event ThreadFinished()
    
    Public Property Get ThreadID() As Long
        ThreadID = App.ThreadID
    End Property
    
    Public Function GetValue() As Long
        GetValue = frmThread.GetValue()
    End Function
    
    Sub ShowFormWithCalculation(Key As String)
        frmThread.Caption = Key
        frmThread.Show vbModal
        RaiseEvent ThreadFinished
    End Sub
    The class has an event ThreadFinished, which is generated when the calculation is finished. GetValue method gets the current value of the counter. Method ShowFormWithCalculation starts calculation.
    Form code frmThread.frm
    Code:
    Dim abort   As Boolean
    Dim value   As Long
    
    ' // Get calculated value
    Public Property Get GetValue() As Long
        GetValue = value
    End Property
    
    ' // Long-long process
    Public Sub RunCycle()
    
        Do Until abort Or value = 150000
            
            lblNum.Caption = Format(value, "000000")
            lblNum.Refresh
            value = value + 1
            
            If (value And &HFF) = 0 Then DoEvents
            
        Loop
        
        Unload Me
    End Sub
    
    Private Sub cmdRun_Click()
        RunCycle
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        abort = True
    End Sub
    Ok. You're asked to do, like the above code. It would be easier not to use the form.
    Consider a client application.
    Standart module modMain.bas:
    Code:
    ' modMain.bas - main module
    ' © Кривоус Анатолий Анатольевич (The trick), 2015
     
    Option Explicit
     
    Public Type UUID
        Data1           As Long
        Data2           As Integer
        Data3           As Integer
        Data4(0 To 7)   As Byte
    End Type
    
    Public Declare Function GetMem1 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
    Public Declare Function GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    Public Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleW" (ByVal lpModuleName As Long) As Long
    Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    Public Declare Function CreateThread Lib "kernel32" (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 Function CoInitialize Lib "ole32" (pvReserved As Any) As Long
    Public Declare Function CoUninitialize Lib "ole32" () As Long
    Public Declare Function CoMarshalInterThreadInterfaceInStream Lib "ole32.dll" (riid As UUID, ByVal pUnk As IUnknown, ppStm As Long) As Long
    Public Declare Function CoGetInterfaceAndReleaseStream Lib "ole32.dll" (ByVal pStm As Long, riid As UUID, pUnk As Any) As Long
    Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    Public Declare Function SetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
    Public Declare Function ResetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
    Public Declare Function CreateEvent Lib "kernel32" Alias "CreateEventW" (lpEventAttributes As Any, ByVal bManualReset As Long, ByVal bInitialState As Long, ByVal lpName As Long) As Long
    Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Public Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, lpiid As UUID) As Long
    
    Public Const PAGE_EXECUTE_READWRITE         As Long = &H40&
    Public Const INFINITE                       As Long = -1&
    Public Const IID_IUnknown                   As String = "{00000000-0000-0000-C000-000000000046}"
    
    Public Type ThreadData
        hEvent  As Long     ' Synchronization object
        IStream As Long     ' Stream object receiving a pointer of marshal-object prjSMT.Thread
        key     As String   ' Parameter of method ShowFormWithCalculation
    End Type
    
    ' // Remove crashes of Declared-functions, sacrificing Err.LastDllError
    ' // If used tlb for API-call, then not used.
    Public Sub RemoveLastDllError()
        Dim hMod    As Long
        Dim lpProc  As Long
        ' Get function address __vbaSetSystemError
        hMod = GetModuleHandle(StrPtr("msvbvm60"))
        lpProc = GetProcAddress(hMod, "__vbaSetSystemError")
        ' Make "ret" opcode
        VirtualProtect lpProc, 1, PAGE_EXECUTE_READWRITE, 0
        GetMem1 &HC3, ByVal lpProc
    End Sub
     
    ' // Thread
    Public Function ThreadProc(value As ThreadData) As Long
        Dim obj     As prjSMT.Thread
        Dim iid     As UUID
        ' Initialization of COM
        CoInitialize ByVal 0&
        ' Createing object - prjSMT.Thread
        Set obj = CreateObject("prjSMT.Thread")
        IIDFromString StrPtr(IID_IUnknown), iid
        ' Make marshalling
        CoMarshalInterThreadInterfaceInStream iid, obj, value.IStream
        ' Initialization success
        SetEvent value.hEvent
        ' Call method
        obj.ShowFormWithCalculation value.key
        ' Remove object
        Set obj = Nothing
        ' Uninitialize
        CoUninitialize
    End Function
    Form with controls - frmMain.frm:
    Code:
    Option Explicit
    
    Dim col As Collection
    
    ' // Asynchronous event from another threads
    Public Function NewEvent(obj As prjSMT.Thread)
        Dim n As Long
        
        MsgBox "Calculation finished " & obj.ThreadID
        ' Remove from listbox
        For n = 0 To lstThreads.ListCount - 1
            If lstThreads.List(n) = obj.ThreadID Then lstThreads.RemoveItem (n): Exit For
        Next
        
    End Function
    
    Private Sub cmdCreateThread_Click()
        Dim param   As ThreadData
        Dim iid     As UUID
        Dim hThread As Long
        Dim obj     As IUnknown
        Dim handler As clsEventHandler
        Dim tid     As Long
    
        ' Warning! This key should pass as copy. This example is incorrect.
        param.key = InputBox("Input window name")
        ' Create event
        param.hEvent = CreateEvent(ByVal 0&, 1, 0, 0)
        ' Create new thread
        hThread = CreateThread(ByVal 0&, 0, AddressOf ThreadProc, ByVal VarPtr(param), 0, tid)
    
        If hThread = 0 Then
            MsgBox "Error creating thread", vbCritical
            Exit Sub
        End If
    
        CloseHandle hThread
        ' Wait object initialization
        WaitForSingleObject param.hEvent, INFINITE
        ' Remove event
        CloseHandle param.hEvent
        ' If success
        If param.IStream Then
            IIDFromString StrPtr(IID_IUnknown), iid
            ' Get marshalled interface
            CoGetInterfaceAndReleaseStream param.IStream, iid, obj
            ' Add to threads collections
            Set handler = New clsEventHandler
            Set handler.Producer = obj
            Set handler.receiver = Me
            col.Add handler, CStr(tid)
            ' Add to listbox
            lstThreads.AddItem CStr(tid)
        Else
            MsgBox "Error creating object", vbCritical
            End
        End If
        
    End Sub
    
    ' // Get current value from selected thread
    Private Sub cmdGet_Click()
        Dim obj As prjSMT.Thread
        Dim key As String
        
        If lstThreads.ListIndex < 0 Then Exit Sub
        
        Set obj = col(lstThreads.List(lstThreads.ListIndex)).Producer
        
        MsgBox obj.GetValue()
    End Sub
    
    Private Sub Form_Load()
        ' Patching runtime
        RemoveLastDllError
        Set col = New Collection
    End Sub
    And the helper class - clsEventHandler.cls, which allows you to handle the event object Thread:
    Code:
    ' // Class for receiving and processing event from a prjSMT.Thread object
    
    Option Explicit
    
    Public receiver     As frmMain
    
    Dim WithEvents obj  As prjSMT.Thread
    
    Public Property Set Producer(newObj As prjSMT.Thread)
        Set obj = newObj
    End Property
    Public Property Get Producer() As prjSMT.Thread
        Set Producer = obj
    End Property
    
    Private Sub obj_ThreadFinished()
        receiver.NewEvent obj
    End Sub
    Compile the both code as Native-code. Later, I'll do an example using only one project StandartEXE, ie no external dependencies.
    www.youtube.com/watch?v=8TbdSiZRxm8
    Attached Files Attached Files

  39. #39
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Now that is complicated!
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  40. #40
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: Can ActiveX EXE be Reg-Free or run without Administrator rights?

    Use module modMultiThreading.bas as is. Just insert it into your project and do not think about how it works, take it as a given. Also, do not forget to add a reference type library.
    Using the function vbCreateThread can create threads where the runtime is already initialized (what used to be impossible).
    Thread function:
    Code:
    Public Type ThreadData
        key As String
        evt As Long
        frm As frmThread
    End Type
    
    Public Sub ThreadProc(dat As ThreadData)
        Dim frm As frmThread
        ' Create new instance of frmThread.frm
        Set frm = New frmThread
        ' Set output parameter
        Set dat.frm = frm
        ' Set caption
        frm.Caption = dat.key
        ' Success
        SetEvent dat.evt
        ' Show form
        frm.Show vbModal
    End Sub
    Called by:
    Code:
    Private Sub cmdCreateThread_Click()
        Dim param   As ThreadData
        Dim hThread As Long
        Dim handler As clsEventHandler
        Dim tid     As Long
    
        ' Warning! This key should pass as copy. This example is incorrect.
        param.key = InputBox("Input window name")
        ' Create event
        param.evt = CreateEvent(ByVal 0&, 1, 0, 0)
        ' Create new thread
        hThread = vbCreateThread(ByVal 0&, 0, AddressOf ThreadProc, ByVal VarPtr(param), 0, tid)
    
        If hThread = 0 Then
            MsgBox "Error creating thread", vbCritical
            Exit Sub
        End If
    
        CloseHandle hThread
        ' Wait object initialization
        WaitForSingleObject param.evt, -1
        ' Remove event
        CloseHandle param.evt
    
    End Sub
    Bear in mind that in the example there is no synchronization. This can cause problems. Therefore, before using multithreading need to become familiar with it. To us falls into the hands of this wonderful tool as multithreading, but also on us great responsibility (such as in C ++). To many shared objects must be organized to synchronize access. You can use mutexes, critical sections, semaphores, etc. Also in this example, no marshaling, so each object lives in the thread in which it was created. Thus, events are generated in the other thread (as opposed to the 1st example). You can verify this by looking App.ThreadID value inside the event handler NewEvent.
    Attached Files Attached Files

Page 1 of 2 12 LastLast

Tags for this Thread

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