为什么我无法处理Runspace?

时间:2016-02-29 00:16:28

标签: multithreading powershell runtime-error powershell-v2.0 runspace

因为我的雇主不想使用编译软件,所以他们要求我创建一个使用PowerShell并行ping一系列设备的GUI。我的PowerShell脚本由该表单上的表单和按钮组成,用于ping设备。为了防止GUI锁定,我使用Runspace将ping操作卸载到一个单独的线程。我可以ping设备并使用来自Runspace的信息更新Form,但是当我完成应用程序时,我无法关闭/处理Runspace,因此即使在应用程序退出后它也会继续运行。

下面提供的函数ping localhost 10次,并将结果添加到GUI中的ListView。

Function PingDevices
{
    Write-Host "Pinging Devices"
    $items = $StorePingInfo_ListView.Items
    $ScriptBlock = 
    {
        $a = 0
        for(;$a -lt 10; $a++)
        {
            $PingResult = Test-Connection 127.0.0.1 -Count 1
            #[System.Windows.Forms.MessageBox]::Show($PingResult)
            $items.Add("Name").SubItems.Add($PingResult)
            sleep 1
        }
    }
    $runspace = [RunspaceFactory]::CreateRunspace()
    $runspace.Open()
    $runspace.SessionStateProxy.SetVariable('Items',$items)

    $powershell = [System.Management.Automation.PowerShell]::create()
    $powershell.Runspace = $runspace
    $powershell.AddScript($ScriptBlock)
    $AsyncHandle = $powershell.BeginInvoke()

}

Function CleanupResources
{
    #When I try to clean up the resources I get Null errors
    Write-Host "AsyncHandle is Null = "($AsyncHandle -eq $null)
    $data = $powershell.EndInvoke($AsyncHandle)
    $powershell.Dispose()
    $runspace.Close()
}

关闭应用程序时出现的错误是

Pinging Devices
AsyncHandle is Null =  True
You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:673 char:5
+     $data = $powershell.EndInvoke($AsyncHandle)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:674 char:5
+     $powershell.Dispose()
+     ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:675 char:5
+     $runspace.Close()
+     ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

我认为这个问题正在发生,因为Runspace正在执行,但是当它运行不正常时就会发生。但是当它全部耦合到像

这样的相同函数内时,它成功关闭而没有错误
Function PingDevices
{
    Write-Host "Pinging Devices"
    $items = $StorePingInfo_ListView.Items
    $ScriptBlock = 
    {
        $a = 0
        for(;$a -lt 10; $a++)
        {
            $PingResult = Test-Connection 127.0.0.1 -Count 1
            #[System.Windows.Forms.MessageBox]::Show($PingResult)
            $items.Add("Name").SubItems.Add($PingResult)
            sleep 1
        }
    }
    $runspace = [RunspaceFactory]::CreateRunspace()
    $runspace.Open()
    $runspace.SessionStateProxy.SetVariable('Items',$items)

    $powershell = [System.Management.Automation.PowerShell]::create()
    $powershell.Runspace = $runspace
    $powershell.AddScript($ScriptBlock)
    $AsyncHandle = $powershell.BeginInvoke()
    $data = $powershell.EndInvoke($AsyncHandle)
    $powershell.Dispose()
    $runspace.Close()
}

如何让Runspace在其所在的同一函数之外释放所有资源?

1 个答案:

答案 0 :(得分:1)

$powershell很可能不是全局变量,因此您有2个不同的变量$powershell,一个在函数PingDevices()的上下文中填充,另一个(空)一个在函数CleanupResources()的上下文中。使用scope modifier更改变量的范围以避免这种情况:$script:powershell(或$global:powershell)。