Powershell 实现 Switch 语句
Powershell implement Switch Statement
我想实施一个
-平行线
切换到我的一个脚本
非并行版本:
$tmpArray | ForEach-Object {
#region ... local Variables
$stepWidthLocal = $stepWidth
<#
my code
#>
并行功能:
$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 语句而不复制整个代码(块 <# my code#>)。
这可能吗?
$arguments = @{ }
if ($myParallel) {
$arguments = @{ parallel = $true; $throttlelimit = 10 }
}
$tmpArray | ForEach-Object @arguments {
...
}
您可以将可重用代码定义为script block, but note that you won't be able to use it directly in your ForEach-Object
-Parallel
script block and instead have to recreate it there, via its string representation passed to the static [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:
引用。
我想实施一个 -平行线 切换到我的一个脚本
非并行版本:
$tmpArray | ForEach-Object {
#region ... local Variables
$stepWidthLocal = $stepWidth
<#
my code
#>
并行功能:
$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 语句而不复制整个代码(块 <# my code#>)。
这可能吗?
$arguments = @{ }
if ($myParallel) {
$arguments = @{ parallel = $true; $throttlelimit = 10 }
}
$tmpArray | ForEach-Object @arguments {
...
}
您可以将可重用代码定义为script block, but note that you won't be able to use it directly in your ForEach-Object
-Parallel
script block and instead have to recreate it there, via its string representation passed to the static [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 提出了一种选择加入机制,允许将调用者的定义复制到每个线程,从而无需