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