Invoke-Parallel
Invoke-Parallel copied to clipboard
Get-RunspaceData error: Collection was modified; enumeration operation may not execute
I am leveraging Invoke-Parallel to process VM actions in parallel in an Azure Automation runbook:
$AzureRMVMs | Invoke-Parallel -ScriptBlock {
$ARMVM = $PSItem
$VMStatus = $ARMVM | Get-AzureRmVM -Status | Select-Object Name, @{n = 'PowerState'; e = {($PSItem.Statuses | Where-Object Code -Like "*PowerState*").DisplayStatus}}
switch ($using:VMAction) {
'Start' {
if ($VMStatus.PowerState -ne 'VM running') {
Write-Output "VM $($ARMVM.Name) is not running - starting"
$ARMVM | Start-AzureRmVM
} else {
Write-Output "VM $($ARMVM.Name) is already running - no action triggered"
}
}
'Stop' {
if ($VMStatus.PowerState -eq 'VM running') {
Write-Output "VM $($ARMVM.Name) is running - stopping"
$ARMVM | Stop-AzureRmVM -Force
} else {
Write-Output "VM $($ARMVM.Name) is already stopped - no action triggered"
}
}
'Default' {Write-Output "VM Action $($using:VMAction) not defined in runbook, no action taken"}
}
} -RunspaceTimeout 300 -NoCloseOnTimeout
This works as expected, however, the following error is generated in the error stream: Get-RunspaceData : Collection was modified; enumeration operation may not execute. At Invoke-Parallell 542 char:13
-
Get-RunspaceData -wait -
~~~~~~~~~~~~~~~~~~~~~~- CategoryInfo : CloseError: (:) [Write-Error], InvalidOperationException
- FullyQualifiedErrorId : Get-RunspaceData
Any idea what might be causing this?
Nice catch!
Indeed there is a collection modification inside a foreach loop
The simplified version of this code is:
Foreach($runspace in $runspaces) {
...
$temphash = $runspaces.clone()
$temphash | Where-Object { $_.runspace -eq $Null } | ForEach-Object {
$Runspaces.remove($_)
}
...
}
https://github.com/RamblingCookieMonster/Invoke-Parallel/blob/master/Invoke-Parallel/Invoke-Parallel.ps1#L325-L328
UPD: nevermind, it happens outside of this loop, it should be something else...