Results 1 to 40 of 62

Thread: VB6 Threading-Examples using the vbRichClient5 ThreadHandler

Threaded View

  1. #34

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: VB6 Threading-Examples using the vbRichClient5 ThreadHandler

    Quote Originally Posted by ColinE66 View Post
    ...it turns out, as I've since observed that any thread that is exited whilst inside a loop is susceptible to this crashing.
    Was not able to reproduce that on either Win8.1 nor Win10 - but got "successful" on WinXP...

    Studying the code in your ThreadDll (JobRunner.dll) - I was able to prevent the crashes, by adding
    an additional CancelCheck-line into your Main-Loop:
    Code:
    Public Sub Test(pCommand As String)
    Dim i As Long
    
       mCancelled = False
       For i = 1 To 20
          If Cancelled Then Exit Sub
          RaiseEvent Iteration(i)
          ExecCmd pCommand
       Next i
    
       RaiseEvent JobComplete
    
    End Sub
    The idea behind it being simply, to *prevent* the ThreadHandler-mechanism, to send "any more events after an external cancelling"
    (via the Named-Pipe I use underneath for communication)...

    Since a clientside CancelExecution will (in addition to setting a "Cancel-Flag" in shared memory) also close the "communication-channel" (the "old pipehandle") -
    followed by re-opening a new pipe-handle immediately after that (for the next call of a "Public Main-Routine" in your Server-Dll).

    I assume, that an attempt to use the (already closed, or "marked for close") "old pipe-handle" (by trying to send Event-Data over it from the server-side),
    is causing the crashes (at least on XP - probably also on Vista and Win7).

    Will try to look into it, when I find time (to make it more bullet-proof, ignoring Event-Send-Requests when the Thread-Handler-Classes are in "CancelExecution-state") -
    though the best way to prevent these crashes seems to me, to really make sure to leave the "Main-Public-Function" as early as possible, when an outside Cancelling was detected
    (no matter how deep you were in some private Sub-Routines - the Cancel-Exits should be honored "further up the stack" as early as possible as well...).

    Addition:
    Looking further at the code in your threaded JobRunner.dll, I've seen that you're waiting for
    5000msec (5seconds) for the shelled process in question to be finished (via WaitForSingleObject).
    During that time, the thread will not be able to detect outside cancelling -
    and that "clashes" with: TH.TimeoutSecondsToHardTerminate (which is by default at 3seconds).

    Hard thread-termination (via TerminateThread-API, which is called under the covers when TH goes out of scope) needs to be avoided -
    better would be, to allow the thread to close "gracefully" - by ensuring a TH.TimeoutSecondsToHardTerminate
    which is greater than the "maximum-time the thread-dll-class cannot react to outside cancel-signalling".

    And another idea would be (since you already use other processes to do the actual work, which are by definition "asynchronous"),
    to not use any threading-helpers at all - instead a simple "Process-Pool-Class" could be enough, which checks via an internal timer,
    whether the "shelled processes" are finished with their Job(s) - or not).


    Here a simple "wireframe-class" you could expand on, making some experiments:
    (the workhorse here is the Helper-Object, which is returned by Wsh.Exec(CmdLine)...
    Code:
    Option Explicit
     
    Private Wsh As Object, Processes As New Collection
    Private WithEvents tmrCheckProcesses As cTimer
    
    Private Sub Class_Initialize()
      Set Wsh = CreateObject("WScript.Shell")
      Set tmrCheckProcesses = New_c.Timer(100, True)
    End Sub
    
    Public Sub AddAndExec(ByVal CmdLine As String)
      Processes.Add Wsh.Exec(CmdLine)
    End Sub
    
    Private Sub tmrCheckProcesses_Timer()
      Const WshRunning = 0, WshFinished = 1, WshFailed = 2
      Dim i As Long, P As Object
      
      On Error Resume Next
     
        For i = Processes.Count To 1 Step -1 'loop backwards, to be able to delete from the Collection
          Set P = Processes(i)
          Select Case P.Status
             Case WshRunning
               'set a flag to the outside, or something, signalling this state
             Case WshFinished 'successful finishing
               Processes.Remove i 'a normal remove from the collection should be enough
             Case WshFailed
               Processes.Remove i 'remove this from the Col as well,
               P.Terminate 'but just in case the process is still linering, try to terminate it as well
               
               'If P.ExitCode = SomeValue Then
                 'just to hint at another property, the Wsh-Process-Object offers
               'End If
          End Select
        Next
        
      If Err Then Err.Clear
    End Function

    HTH

    Olaf
    Last edited by Schmidt; Jul 13th, 2019 at 05:41 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