Author Posts

September 6, 2013 at 12:50 pm

Hi all,

So! I'm using a runspace pool to parallelize a task. One of these gets hung up (running query.exe user /server:blah).

How do I end a PowerShell pipeline asynchronously? I see a BeginStop method, but it is a bit beyond my understanding. Has anyone used this, or would it be easy to provide an example of how to use this in PowerShell? Here is the code to reproduce the issue (leave notepad.exe up, reference $temp.powershell and $temp.runspace):


#test runspace

$scriptblock = {
param($_, $parameter)
Start-Process notepad.exe -wait
}

#init vars
$throttle = 1
$parameter = "blah"
$objectToProcess = "someServer"

#Build runspace pool
$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspacepool.Open()

#array for runspace tracking
$Script:runspaces = New-Object System.Collections.ArrayList

#create powershell instance and add script/args
$powershell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($objectToProcess).AddArgument($parameter)

#assign powershell instance to runspace pool
$powershell.RunspacePool = $runspacepool

#build a temp object with runspace info, add it to runspace tracking array
$temp = "" | Select-Object PowerShell, StartTime, object, Runspace
$temp.PowerShell = $powershell
$temp.StartTime = get-date
$temp.object = $objectToProcess
$temp.Runspace = $powershell.BeginInvoke()
$runspaces.Add($temp) | Out-Null

#Issue here. I want to stop a powershell pipeline, presumably using BeginStop
#$temp.powershell.BeginStop(< #this is over my head!#>)

Your insight would be greatly appreciated!

September 6, 2013 at 3:14 pm

Odd, turns out you can't edit a post?

Anyhow, Jaykul helped out a bit – just need to provide a callback scriptblock. Now (presumably) the powershell pipeline is stopped and I dispose of it... Unfortunately, when I call the close method on the runspacepool, it hangs! If I use beginclose on the runspacepool, bye bye powershell. My apologies if this is simple stuff, it's beyond my understanding!

Any tips?


#test runspace
$scriptblock = {
param($_, $parameter)
Start-Process notepad.exe -wait
}

#init vars
$throttle = 1
$parameter = "blah"
$objectToProcess = "someServer"

#Build runspace pool
$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspacepool.Open()

#array for runspace tracking
$Script:runspaces = New-Object System.Collections.ArrayList

#create powershell instance and add script/args
$powershell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($objectToProcess).AddArgument($parameter)

#assign powershell instance to runspace pool
$powershell.RunspacePool = $runspacepool

#build a temp object with runspace info, add it to runspace tracking array
$temp = "" | Select-Object PowerShell, StartTime, object, Runspace
$temp.PowerShell = $powershell
$temp.StartTime = get-date
$temp.object = $objectToProcess
$temp.Runspace = $powershell.BeginInvoke()
$runspaces.Add($temp) | Out-Null

#Issue here. I want to stop a powershell pipeline, presumably using BeginStop
#$temp.powershell.BeginStop(< #this is over my head!#>)
$callback = { (New-Object System.Threading.ManualResetEvent($false) ).set() }
$temp.powershell.beginstop($callback,$null)

#close the runspace. this hangs
$runspacepool.close()

#alternatively, beginclose the runspace. this kills my powershell session
$runspacepool.close($callback,$null)

September 6, 2013 at 4:48 pm

Try PowerShell.Stop() instead of BeginStop. BeginStop is an asynchronous method, but your code structure looks like you'd be better off using the synchronous version.

September 6, 2013 at 5:56 pm

Hi Dave,

To clarify, I'm doing this for an update to Invoke-Parallel which was a 'I have no idea what I'm doing here but this makes things faster' first stab...

The updated code is here. One of two things happen when I run this with a timeout and a thread freezes (script block running an external command that hangs): I get stuck at closing the runspacepool (previously got stuck when disposing the powershell instance), or PowerShell crashes.

So basically, I want to forcefully kill the powershell instance. If you ctrl-f for '#this is not working properly', that is where I presume I am stumbling. Also at the very end of the function when I close the runspacepool.

My apologies for the convoluted description : )

September 6, 2013 at 6:35 pm

Even looking at the complete code, it looks to me like you should be using the synchronous version ( Stop() instead of BeginStop() ). I'm not sure what the consequences are of calling BeginStop() and then immediately calling Dispose() on the object.

On a side note, you should be able to skip that and just call Dispose(), if you prefer. Among the other things that it does, Dispose() will call Stop(), if it's needed.

September 6, 2013 at 6:59 pm

Hi again Dave,

Yeah, that's how the original function was written / borrowed from Boe. $runspace.powershell.dispose(). This is where it hangs.

Adding the beginstop() gets me a bit further, but now the session hangs or Powershell crashes when closing the runspacepool.

September 9, 2013 at 5:50 am

Hi all,

Any thoughts? Is there no way to kill a stuck powershell pipeline? Was hoping to go with something generic where I don't need to rely on the powershell code running to avoid these issues. For now just using diagnostics.process and waitforexit() on the process that gets hung up occasionally.

Cheers!