在PowerShell版本7(预览版3)中引入了Foreach-Object -Parallel命令,该命令用于并行执行管道输入,本文对此进行了详细说明。
请注意:Foreach-Object和Foreach命令是相同的,但是我们不能编写Foreach -Parallel命令,因为没有这样的命令,我们需要使用完整的命令Foreach-Object -Parallel。
运行并行对象的简单示例。
1..10 | ForEach-Object -Parallel{ $_ * 1000 Sleep 1 }
输出结果
1000 2000 3000 4000 5000 6000 7000 8000 9000 10000
让我们比较带有和不带有-Parallel参数的计时。
$time1 = Measure-Command { 1..10 | ForEach-Object -Parallel{ $_ * 1000 Sleep 1 } } Write-Output "Parallel Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "
输出结果
Parallel Time : Minutes : 0 , Seconds : 2 , Milliseconds : 2500.9792
$time1 = Measure-Command { 1..10 | ForEach-Object { $_ * 1000 Sleep 1 } } Write-Output "Sequential Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "
输出结果
Sequential Time : Minutes : 0 , Seconds : 10 , Milliseconds : 10062.0786
您可以看到以上两个执行之间的显着差异,即并行运行比顺序运行快得多。
还有一个参数支持foreach-Object循环的并行性:-ThrottleLimit表示并行执行的线程数。默认情况下,油门极限为5。增加油门极限时,请参见时间差。
$time1 = Measure-Command { 1..10 | ForEach-Object -Parallel{ $_ * 1000 Sleep 1 } -ThrottleLimit 10 } Write-Output "Sequential Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "
输出结果
Parallel Time : Minutes : 0 , Seconds : 1 , Milliseconds : 1615.4921
如果您比较第一个并行时间示例,那么第二个示例会更快,因为我们增加了油门限制。当您增加油门限制时,请确保将哪个命令用于并行执行,并已将油门限制数作为输入传递,否则系统将不执行脚本,因为会生成许多PowerShell线程。
您还可以将此命令作为后台作业运行,因为它支持-AsJob参数。
$fjob = 1..10 | ForEach-Object -Parallel{ $_ * 1000 Sleep 1 } -ThrottleLimit 10 -AsJob $fjob | Receive-Job
另一个远程命令与foreach-Object -Parallel之间的区别在于,此命令在称为命名空间的同一上下文中并行运行作业,而其他远程命令使用-ComputerName参数或Invoke-Command和这就是远程计算机并行执行要快得多的原因。
在PS版本7中使用Parallel foreach循环时,在并行循环中唯一可见的变量是管道变量,可以使用Using:关键字访问变量或对象之外的其他变量。例如,
$computers = "Test1-Win2k12", "test1-Win2k16" $command = "Win32_OperatingSystem" $computers | ForEach-Object -Parallel { Get-CimInstance $using:command -ComputerName $_ }
您可以在上面的脚本中看到,只有$computers可以通过$_在Foreach循环内访问,但是要访问$command,我们需要使用$using:Command,因为它不在循环范围之内,但事实并非如此一个简单的foreach循环。