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:ODFMOneDriveFMFamily Photos") -replace "TIF", "JPG")
    $b=(($a -replace "$basePath", "O:ODFMOneDriveFMFamily 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 ответ
1

Итак, в PowerShell новые -parallel схема, вам нужно использовать $using:basePath вместо просто $basePath для всех вызовов внутри параллельного цикла. Это потому, что переменная определена в родительской области.

Многопоточные и параллельные операции представляют собой уникальный набор сложностей, которые в совокупности называются параллелизмом или несколькими параллельными проблемами, и поэтому требуют принятия специальных мер, чтобы гарантировать, что память, к которой обращаются потоки, находится в безопасном состоянии для использования.

Powershell реализует поточный контекст, называемый RunSpace, и создает его для каждой параллельной операции. Область выполнения содержит копию каждой переменной, объявленной в этом блоке, и может работать только с этими скопированными экземплярами переменных. это означает, что если один поток изменяет свою версию переменной, другие потоки не увидят этого изменения.

Однако, чтобы получить доступ к переменной, которая входит в область видимости для нескольких потоков, мы должны изучить такие методы, как Mutex и блокировки. Блокировка потока — это простая конструкция, предотвращающая изменение значения во время его использования. В Powershell они сделали это легко, добавив $using: ключевое слово для ссылки на переменные более высокого уровня.

Подробнее см. Здесь: https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

  • Благодарю. Это решило проблему. Я ценю дополнительное чтение.

    — Брайан
    20 часов назад

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *