[PowerShell] Methods – BeginStop

This topic contains 6 replies, has 2 voices, and was last updated by  Warren Frame 4 years ago.

  • Author
    Posts
  • #9975

    Warren Frame
    Participant

    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!

  • #9977

    Warren Frame
    Participant

    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)

  • #9978

    Dave Wyatt
    Moderator

    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.

  • #9979

    Warren Frame
    Participant

    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 : )

  • #9982

    Dave Wyatt
    Moderator

    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.

  • #9984

    Warren Frame
    Participant

    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.

  • #10009

    Warren Frame
    Participant

    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!

You must be logged in to reply to this topic.