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

Multithreading 为什么我无法处理运行空间?,multithreading,powershell,runtime-error,powershell-2.0,runspace,Multithreading,Powershell,Runtime Error,Powershell 2.0,Runspace,因为我的雇主不想使用编译过的软件,他们要求我创建一个GUI,使用PowerShell并行ping一系列设备。我的PowerShell脚本由一个窗体和窗体上用于ping设备的按钮组成。为了防止GUI锁定,我使用运行空间将ping卸载到单独的线程。我能够ping设备并使用运行空间中的信息更新表单,但是当我完成应用程序时,我无法关闭/处置运行空间,因此即使在应用程序退出后,它也会继续运行 下面提供的函数ping localhost 10次,并将结果添加到GUI中的ListView中 Function

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

下面提供的函数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
如何让运行空间在其驻留的同一函数之外释放其所有资源?

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

您可以通过在同一类中使用
System.Net.NetworkInformation.SendAsync
PingCompleted
事件来完全消除备用运行空间。这很有效!非常感谢你。您能更深入地解释一下为什么在其他函数中我可以定义一个变量(例如$one=1)并从其他函数调用它,但在运行空间中,如果引用名称前面没有$Global前缀,我就无法从其他函数调用它的引用吗?@Loligans应该没有区别。如果它在其他地方工作,那么在函数上下文中使用它之前,很可能已经有了一个同名的全局变量。我将对此进行研究,但将该变量设置为全局变量解决了这个问题。再次感谢!
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()
}