locked
Problem kill runspace threads. RRS feed

  • Question

  • I've got a working multithreaded powershell script that has two threads doing work independently and passing information back and forth with shared context (using SYnchroot for locking etc).

    THe whole thing spins up just find and the work proceeds as intended.   But under certain event's (bugs in in the code etc) one of the threads will exit.    These events aren't normal and I will eventually work out those things that are causing exceptions.   But when they do happen I need to kill the other threads.

    I'm trying to call Close, Dispose etc and don't seem to be able to kill these threads.   Even when I kill Powershell ISE the threads hang out there and I need to kill them with Task Manager.   This is a pain in the rear during development/debugging.

    Hopefully someone out there can clue me in to what I'm doing wrong.

    Here is code for 

    Add-Type -AssemblyName System.speech
    $arrayList = New-Object System.Collections.ArrayList 
    $gate2 = New-Object System.Collections.ArrayList
    $execGate1 = New-Object System.Collections.ArrayList
    $execGate2 = New-Object System.Collections.ArrayList
    $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer
    $commandIndex = 0
     
    $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('arrayList', $arrayList, $null)))
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('gate2', $gate2, $null)))
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('speak', $speak, $null)))
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('commandIndex', $commandIndex, $null)))
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('execGate1', $execGate1, $null)))
    $sessionstate.Variables.Add((New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry('execGate2', $execGate2, $null)))
    
    $runspacepool = [runspacefactory]::CreateRunspacePool(1, 10, $sessionstate, $Host) 
    $runspacepool.Open() 
     
    $ps1 = [powershell]::Create() 
    $ps1.RunspacePool = $runspacepool 
    $null = $ps1.AddScript({ 
    
    ...
    ... Lots of code
    
    $ps2 = [powershell]::Create() 
    $ps2.RunspacePool = $runspacepool  
    $null = $ps2.AddScript({
    
    ...
    ... a bunch more code
    
    $handle1 = $ps1.BeginInvoke()
    $handle2 = $ps2.BeginInvoke()
    
    #
    # THis is my attempt to detect when one of the threads 
    # exists due to an error condition and then kill
    # the other thread.
    #
    # But I always end up with one thread hanging out there
    # that I can only kill with Task Manager
    # 
    while (1) {
         if ($handle1.IsCompleted) {
            Write-Host "$ps1 ended..."
            if (-NOT $handle2.IsCompleted) {
                Write-host "$ps1 ended - killing $ps2"
                $ps2.Stop
                $ps2.Dispose
                $runspacepool.Close
                $runspacepool.Dispose
                }
            return
         }
    
         if ($handle2.IsCompleted) {
            Write-host "$ps2 ended..."
            if (-NOT $handle1.IsCompleted) {
                Write-host "$ps2 ended - killing $ps1"
                $ps1.Stop
                $ps1.Dispose
                $runspacepool.Close
                $runspacepool.Dispose
                }
            return
         }
         Write-host "Watch loop sleeping..."
         Start-Sleep -Seconds 1
    }
    
    
    

    Thursday, April 25, 2019 1:57 AM

All replies

  • This is an issue that likely can't be addressed by a script.

    First you need to know what the thread is from.  How can you tell in Task Manager that it is a thread?

    To end a runspace started with "BeginInvoke" you need to use "EndInvoke".


    \_(ツ)_/

    Thursday, April 25, 2019 5:11 AM
  • In task manager I see the "thread / process" as Powershell ISE.  The thread has a file locked that I can see in Process Monitor.  When I kill the thread/process it unlocks the file.
    Thursday, April 25, 2019 1:59 PM
  • The thread is throwing an exception and is getting locked in memory.  You need to trap the exception and handle it to prevent this.


    \_(ツ)_/

    Thursday, April 25, 2019 2:22 PM