下面的代码隔离了我正在尝试执行的任务。 一旦在 $loopMe 中检查到超过 3 的数字,我希望 foreach-object 循环在所有运行空间中结束,并将 numberOverLimit 的值设置为 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"
}
预期结果
0
1
2
3
3 2 1 0
True
A number was over the limit
实际结果
0
1
4
2
3
3 2 1 0
False
All is good
最佳答案
您的并行循环看不到您的 $global:numberOverLimit
变量,即使可以看到,它也无法更新 bool 值(a value type )。您只能更新reference type来自并行循环,这就是我在本例中使用 Get-Variable
的原因。
另请注意,使用 break
in a script block :
Using
break
inside a pipelinebreak
, such as aForEach-Object
script block, not only exits the pipeline, it potentially terminates the entire runspace.
提早停止管道的唯一内置方法是使用Select-Object -First
,您可以将并行循环通过管道传输到它,并将任何内容输出到 stdout 以终止并行循环:
最后,您应该在更新 PSVariable
实例之前确保线程安全,因为您需要使用某种锁定机制,Monitor.Enter
就是本例中使用的。
$addToMe = [System.Collections.Concurrent.ConcurrentBag[psobject]]::new()
$numberOverLimit = $false
$psvar = Get-Variable numberOverLimit
0..5 | ForEach-Object -ThrottleLimit 6 -Parallel {
$localAddToMe = $using:addToMe
$psvar = $using:psvar
Write-Host $_
if($_ -gt 3) {
[System.Threading.Monitor]::Enter($psvar)
$psvar.Value = $true
[System.Threading.Monitor]::Exit($psvar)
return 'something, whatever here'
}
$localAddToMe.Add($_)
} | Select-Object -First 1 | Out-Null
Write-Host $addToMe
Write-Host $numberOverLimit
if($numberOverLimit) {
Write-Host 'A number was over the limit'
return
}
else {
Write-Host 'All is good'
}
关于powershell - 如何退出 ForEach-Object Parallel 并更新 Powershell 7 中运行空间之外的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76100138/