The code below isolates the task I am trying to do. Once a number over 3 is checked in $loopMe, I want the foreach-object loop to end across all runspaces and that the value of numberOverLimit is set to true.
$loopMe = [System.Collections.ArrayList]@()
for($index = 0; $index -lt 5; $index++){
$loopMe.Add($index)>$null;
}
$global:numberOverLimit=$false
$addToMe= [System.Collections.Concurrent.ConcurrentBag[psobject]]::new()
$loopMe | Foreach-Object -ThrottleLimit 6 -Parallel{
$localAddToMe=$using:addToMe
Write-Host $_
if($_ -gt 3){
$global:numberOverLimit=$true
break
}
$localAddToMe.Add($_)
}
write-Host $addToMe
Write-Host $numberOverLimit
if($numberOverLimit){
Write-Host "A number was over the limit"
exit
}
else{
Write-Host "All is good"
}
Expected Result
0
1
2
3
3 2 1 0
True
A number was over the limit
Actual Result
0
1
4
2
3
3 2 1 0
False
All is good
Your parallel loop can't see your
$global:numberOverLimitvariable and even if it would, it wouldn't be able to update the boolean (a value type). You can only update a reference type from your parallel loop, which is why I'm usingGet-Variablein this example.Also note, the use of
breakin a script block:The only built-in method to stop a pipeline early is with
Select-Object -First, you can pipe your parallel loop to it and output anything to stdout to terminate your parallel loop:Lastly, you should ensure thread safety before updating your
PSVariableinstance, for that you need to use some sort of locking mechanism,Monitor.Enteris the one used in this case.