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