因为我的雇主不想使用已编译的软件,他们要求我创建一个使用PowerShell并行处理一系列设备的GUI。我的PowerShell脚本包含一个窗体和一个按钮,该窗体用于对设备进行ping操作。为了防止GUI被锁定,我使用Runspace将ping分流到一个单独的线程。我能够ping通设备并使用来自Runspace的信息更新表单,但是当我完成应用程序时,我无法关闭/处理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
我以为是因为运行空间在执行问题发生了什么,但是当它不运行,以及它发生。然而,它没有误差地成功关闭,当这一切被连接在同一个函数内这样
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()
}
我怎样才能运行空间来释放它驻留在同一功能之外的所有资源?
通过在同一个类中使用'System.Net.NetworkInformation.SendAsync'和'PingCompleted'事件,您可以完全摆脱替代运行空间。 –