
При запуске в -Parallel
следующий скрипт не передает $basePath
переменную, объявленную до начала параллельного блока. Вместо этого это нулевое значение. Это не проблема, когда скрипт не запускается в -Parallel
— он передаст значение переменной и запустится так, как и ожидалось. К вашему сведению, я использую 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"
решение1
Так что в новой схеме powershells -parallel
вам нужно использовать $using:basePath
вместо просто $basePath
для всех вызовов внутри параллельного цикла. Это потому, что переменная определена в родительской области видимости.
Многопоточность и параллельные операции представляют собой уникальный набор сложностей, которые в совокупности называются проблемами параллелизма или многоконкурентности, и поэтому требуют принятия специальных мер для обеспечения того, чтобы память, к которой обращаются потоки, находилась в безопасном состоянии для использования.
Powershell реализует потоковый контекст, называемый RunSpace, и создает его для каждой параллельной операции. Runspace содержит копию каждой переменной, объявленной в этом блоке, и может работать только с этими скопированными экземплярами переменных. Это означает, что если один поток изменяет свою версию переменной, другие потоки не увидят этого изменения.
Однако, чтобы получить доступ к переменной, которая находится в области действия нескольких потоков, мы должны рассмотреть такие методы, как Mutex и Locks. Блокировка потока — это простая конструкция, которая предотвращает изменение значения во время его использования. В Powershell это упростили, добавив ключевое $using:
слово для ссылки на переменные более высокой области действия.
Более подробную информацию смотрите здесь:https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/