Results 1 to 32 of 32

Thread: VB6 MultiProcessing (StdExe-IPC via SharedMemory)

Threaded View

  1. #14
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    733

    Question Re: VB6 MultiProcessing (StdExe-IPC via SharedMemory)

    Quote Originally Posted by Schmidt View Post
    This demonstrates, how one can implement robust, asynchronous Workers in VB6 -
    by using a (cross-process) SharedMemory-approach (which is one of the common IPC-mechanisms).

    For convenient usage, the more complex stuff (the MemoryMapping- as well as the CreateProcess-APIs),
    are encapsulated in two generic "Drop-In"-Classes (cIPCMaster and cIPCWorker).

    Those Classes can be used either "split-up" (in separate VB6-Projects for Master and Worker) -
    but also "all-in-one" (when the same Project - or Process - is used to act as Master and Worker both).

    The latter case (using an "all-in-one"-Project), is the most convenient for developing/testing.
    Here the Worker-Process is "shelled" against the same ExeName as the Main- (or Master-) Project,
    using a simple "forking" in Sub Main() ... (as shown below from the content of Demo1 modMain.bas):
    Code:
    Option Explicit
    
    Sub Main() 'Process-Startup-Forking
      If Len(Trim$(Command$)) = 0 Then 'no Cmd-Arg was passed (it was started as the Master-Process)
        fMaster.Show '... so we simply startup the Main-Form
        
      Else 'it was started as a WorkerProcess (pass the CommandLine-Arg into the WorkerRoutine)
        EnterWorkerLoop New cIPCWorker, Trim$(Command$)
      End If
    End Sub
    Above, the blue-colored call represents the "master-fork-path" to your normal "GUI-Project-Code"
    (entered when no Commandline-Param was passed to your Executable).

    And as the magenta-colored routine-name (in the "worker-fork-path") suggests, the upstarting worker is not fired up
    like in an old "classic WebServer-CGI-call" (where the Process exits, after only a single Job was performed).

    Instead the current mechanism is implemented in a way, that the WorkerProcess is fired up once -
    and then enters an "IDLE-loop" (waiting for Jobs, provided by the Master-Process later).
    This way one of the disadvantages of MultiProcessing (the higher Startup-Costs, compared to MultiThreading) is avoided.

    The advantages of doing MultiProcessing instead of threading are:
    - no typelibs, no extra-Dlls are needed
    - in the IDE (after compiling the same Project), the asynchronous workers will behave the same way as in the compiled binary
    - a hard terminate of a worker is possible in a stable and "residue-free" manner (though graceful termination-support is of course built-in)
    - the communication between Master and Worker(s) happens in an absolute "non-blocking" way

    To explain the last point above a bit more... "non-blocking" means, that neither Post- or SendMessage-calls are involved
    (as in VB6-OleBased-Communications between "threaded Apartments", where Events, raised from the Workers will block the Main-Thread) -
    nor are there other mechanisms in play like Mutexes or CriticalSections, which are normally used in conjunction with shared memory...

    Instead the Demo shows, how "state-machine-based" communication (using the shared mem-area) can be implemented.

    The approach is extremely robust, completely IDE- and crash-safe, and "cleans up after itself" under any circumstances:
    - upstarted Worker-Processes will automatically close, when the Master-Class goes out of scope
    - you can even use the IDE-stop-button, whilst asynchronous workers are "deep within a Job" (worker-processes will autoclose nevertheless)

    There is also not a single thing, which is "forbidden to use" in the workers (like in many of the threading-approaches for VB6)...

    The Zip below comes with 3 Demo-Folders (a simple one to get up to speed - and two "medium-difficult" ones for MandelBrot-rendering).

    Ok, here is, what the MandelBrot-Demos will produce (using two Workers, independent from the Main-App):


    And here's the Demo-Zip: IPCSharedMem.zip

    Have fun...

    Olaf
    If I want to pass string data to the shared memory from the main process, how does the working process know the length of the shared string when reading data?


    Public Type RecordType

    str As String * 100 ------Must use a fixed-length string

    End Type

    Now I think of this method to solve this problem

    '====add
    Private Declare Function lstrcpyn _
    Lib "kernel32" _
    Alias "lstrcpynA" (ByVal lpString1 As Any, _
    ByVal lpString2 As Any, _
    ByVal iMaxLength As Long) As Long

    Private Declare Function lstrlen _
    Lib "kernel32" _
    Alias "lstrlenA" (ByVal lpString As Any) As Long
    Private str As String

    Private Sub cmdStart_Click()
    Label2.Caption = ""

    str = "hello:Schmidt" '
    'M.UserDataWrite StrPtr(str), lstrlen(str)
    lstrcpyn M.UserDataPtr, ByVal str, lstrlen(str) + 1
    'MsgBox lstrlen(M.UserDataPtr)
    M.JobState = jobPrepared


    Private Sub DoJob(W As cIPCWorker)

    Dim i As Long

    Dim tmpString As String

    tmpString = Space(lstrlen(W.UserDataPtr))
    lstrcpyn ByVal tmpString, W.UserDataPtr, lstrlen(W.UserDataPtr) + 1

    MsgBox tmpString

    For i = 1 To 100
    W.JobProgress = i / 100
    W.Wait 50 '<- simulate some workload (instead of doing some real stuff)

    If W.MasterWantsToClose Or W.JobState <> wjobProcessing Then Exit Sub 'early exit
    Next
    str = Replace(tmpString, "hello", "thanks")

    lstrcpyn W.UserDataPtr, ByVal str, lstrlen(str) + 1
    W.JobState = wjobFinished 'if the worker-routine reached this point, switch to the next state

    End Sub
    Demo1 Send string.zip

    Do you have other methods?
    Last edited by xxdoc123; Jun 4th, 2018 at 12:38 AM.

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