Me gustaría implementar un cambio paralelo a uno de mis skripts
Versión no paralela:
$tmpArray | ForEach-Object { #region ... local Variables $stepWidthLocal = $stepWidth <# my code #>Función paralela:
$tmpArray | ForEach-Object -ThrottleLimit ($parallelBlocks * 10) -Parallel { #region ... local Variables $stepWidthLocal = $using:stepWidth <# my code #>Lo que no quiero es:
$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 {Quiero algo como esto:
$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 {Ahora quiero crear algún tipo de declaración de cambio sin duplicar el código completo (bloquear <# my code#>).
¿es posible?
$arguments = @{ } if ($myParallel) { $arguments = @{ parallel = $true; $throttlelimit = 10 } } $tmpArray | ForEach-Object @arguments { ... }Puede definir el código reutilizable como un bloque de script , pero tenga en cuenta que no podrá usarlo directamente en su bloque de script ForEach-Object -Parallel y, en su lugar, tendrá que volver a crearlo allí, a través de su representación de cadena pasada a la estática [scriptblock]::Create() ; usando un ejemplo simplificado:
# 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)) } Nota: Esta respuesta contiene una solución análoga para usar una función del alcance de la persona que llama en un bloque de script ForEach-Object -Parallel .
El resultado anterior es algo como lo siguiente:
hi from thread 35 hi from thread 36Nota (a partir de PowerShell 7.2):
ForEach-Object -Parallel previene activamente el uso directo de bloques de secuencias de comandos desde el alcance de la persona que llama (al que se accede a través del alcance $using: ), porque el uso de bloques de secuencias de comandos en subprocesos puede generar problemas de seguridad de subprocesos; curiosamente, sin embargo, el Start-ThreadJob relacionado acepta bloques de script a través $using: - aunque eso puede haber sido un descuido.
El problema n.º 12378 de GitHub analiza este comportamiento, incluida una posible mejora para permitir que ForEach-Object recree automáticamente el bloque de script de manera segura para subprocesos.
$using: sean innecesarias.