Quando executado em -Parallel
, o script a seguir não passa a $basePath
variável declarada antes do início do bloco paralelo. Em vez disso, é um valor nulo. Isso não é um problema quando o script não é executado -Parallel
-- ele passará o valor da variável e será executado conforme o esperado. FYI, estou executando o PS 7.x.
$basePath=((get-location) -replace "\\", "\\")
get-childitem *.tif -recurse | foreach-object -Parallel {
$a=($_ -split "\.tif")[0]
$path=(((split-path $_) -replace "$basePath", "O:\OD\FM\OneDrive\FM\Family Photos") -replace "TIF", "JPG")
$b=(($a -replace "$basePath", "O:\OD\FM\OneDrive\FM\Family Photos") -replace "TIF", "JPG")
if (!(Test-Path -path $path)) {mkdir "$path"}
if (!([system.io.file]::Exists("$b.jpg"))) {
magick convert "$a.tif" -resize 50% -quality 100 -define jpeg:extent=1024KB "$b.jpg"
[console]::foregroundcolor="Green"
echo "`nB`:`t$b`n`n"
}
} -ThrottleLimit 8
[console]::foregroundcolor="White"
Portanto, no novo esquema do powershell
-parallel
, você precisa usar$using:basePath
em vez de apenas$basePath
para todas as invocações dentro do loop paralelo. Isso ocorre porque a variável é definida em um escopo pai.Operações paralelas e de multiencadeamento apresentam um conjunto exclusivo de complicações coletivamente chamadas de problemas de simultaneidade ou multiconcorrência e, portanto, exigem que etapas especiais sejam tomadas para garantir que a memória acessada por encadeamentos esteja em um estado seguro para uso.
O Powershell implementa um contexto encadeado chamado RunSpace e cria um para cada operação paralela. O runspace contém uma cópia de cada variável declarada nesse bloco e só pode operar nessas instâncias copiadas das variáveis. isso significa que se um thread modificar sua versão da variável, outros threads não verão essa mudança.
No entanto, para acessar uma variável que está no escopo de vários threads, devemos examinar técnicas como Mutex e Locks. Um bloqueio de thread é uma construção simples que impede que um valor seja modificado enquanto está sendo usado. No Powershell, eles tornaram isso fácil, adicionando a palavra-
$using:
chave para referenciar variáveis de escopo mais alto.Veja aqui para mais detalhes: https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/