为什么我无法处理运行空间?

Why am I unable to Dispose of Runspace?

因为我的雇主不想使用编译软件,他们要求我创建一个 GUI,使用 PowerShell 并行 ping 一系列设备。我的 PowerShell 脚本由一个表单和一个用于对设备执行 ping 操作的按钮组成。为了防止 GUI 锁定,我使用运行空间将 ping 卸载到一个单独的线程。我能够 ping 设备并使用来自运行空间的信息更新表单,但是当我完成应用程序时,我无法 close/Dispose 运行空间,因此即使在应用程序退出后它仍保持 运行 .

下面提供的函数 ping 本地主机 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 释放它所在的同一函数之外的所有资源?

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