Powershell实现Switch语句



我想实现一个平行切换到我的一个脚本

非并行版本:

$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:引用不必要。
$arguments = @{ }
if ($myParallel) {
$arguments = @{ parallel = $true; $throttlelimit = 10 }
}
$tmpArray | ForEach-Object @arguments {
...
}

相关内容

  • 没有找到相关文章

最新更新