PowerShell: Скрипт выдает параллельные сообщения

PowerShell: Скрипт выдает параллельные сообщения

При запуске в -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/

Связанный контент