我想实现一个平行切换到我的一个脚本
非并行版本:
$tmpArray | ForEach-Object {
#region ... local Variables
$stepWidthLocal = $stepWidth
<#
my code
#>
平行Funktion:
$tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel {
#region ... local Variables
$stepWidthLocal = $using:stepWidth
<#
my code
#>
我不想要的是:
$myParallel = $true
if ($myParallel) {
$tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel {
#region ... local Variables
$stepWidthLocal = $using:stepWidth
<#
my code
#>
} #end $tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel
} #end if($myParallel)
else {
$tmpArray | ForEach-Object {
#region ... local Variables
$stepWidthLocal = $stepWidth
<#
my code
#>
} #end $tmpArray | ForEach-Object {
} #end else {
我想要这样的东西:
$myCode = <#
define my Codeblock
#>
$myParallel = $true
if ($myParallel) {
$tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel {
#region ... local Variables
$stepWidthLocal = $using:stepWidth
$myCode
} #end $tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel
} #end if($myParallel)
else {
$tmpArray | ForEach-Object {
#region ... local Variables
$stepWidthLocal = $stepWidth
$myCode
} #end $tmpArray | ForEach-Object {
} #end else {
现在我想创建某种switch语句,而不需要复制整个代码(block <# my code#>)。
这可能吗?
您可以将可重用代码定义为脚本块,但请注意,您将无法在ForEach-Object
-Parallel
脚本块中直接使用它,而必须在那里重新创建它,通过其字符串表示传递给静态[scriptblock]::Create()
方法;使用一个简单的例子:
# Your reusable code block.
# Note the .ToString() call to obtain its string representation.
$myCodeSource = {
"hi from thread $([System.Threading.Thread]::CurrentThread.ManagedThreadId)"
}.ToString()
1, 2 | ForEach-Object -Parallel {
# ...
# Note: You can pass arguments, if the script block is prepared to handle them.
& ([scriptblock]::Create($using:myCodeSource))
}
注意:此答案包含一个类似的解决方案,用于在ForEach-Object -Parallel
脚本块中使用来自调用者作用域的函数。
上面的输出类似如下:
hi from thread 35
hi from thread 36
注意(从PowerShell 7.2开始):
ForEach-Object -Parallel
主动阻止直接使用调用者作用域的脚本块(通过$using:
访问),因为跨线程使用脚本块会导致线程安全问题;然而,奇怪的是,相关的Start-ThreadJob
确实通过$using:
接受脚本块——尽管这可能是一个疏忽。- 通过字符串表示重新创建脚本块,如上所示,可以绕过此限制。
GitHub issue #12378讨论了这种行为,包括一个可能的增强,让
ForEach-Object
自己以线程安全的方式自动重新创建脚本块。- 更一般地说,GitHub issue #12240提出了一个选择机制,允许将调用者的定义复制到每个线程,使
$using:
引用不必要。
- 更一般地说,GitHub issue #12240提出了一个选择机制,允许将调用者的定义复制到每个线程,使
$arguments = @{ }
if ($myParallel) {
$arguments = @{ parallel = $true; $throttlelimit = 10 }
}
$tmpArray | ForEach-Object @arguments {
...
}