PowerShell: 병렬로 발생하는 스크립트

PowerShell: 병렬로 발생하는 스크립트

에서 실행할 때 -Parallel다음 스크립트는 $basePath병렬 블록이 시작되기 전에 선언된 변수를 전달하지 않습니다. 대신 null 값입니다. 스크립트가 실행되지 않을 때는 문제가 되지 않습니다 -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

따라서 Powershell의 새로운 구성표에서는 병렬 루프 내부의 모든 호출에 대해서만 사용 하는 대신 -parallel사용해야 합니다 . 이는 변수가 상위 범위에 정의되어 있기 때문입니다.$using:basePath$basePath

다중 스레딩 및 병렬 작업은 동시성 또는 다중 동시 문제라고 통칭하는 고유한 문제 집합을 나타내므로 스레드에서 액세스하는 메모리가 사용하기에 안전한 상태인지 확인하기 위해 특별한 조치를 취해야 합니다.

Powershell은 RunSpace라는 스레드 컨텍스트를 구현하고 각 병렬 작업에 대해 하나를 만듭니다. 런타임 공간에는 해당 블록에 선언된 모든 변수의 복사본이 포함되어 있으며 복사된 변수 인스턴스에서만 작동할 수 있습니다. 이는 한 스레드가 변수 버전을 수정하면 다른 스레드는 해당 변경 사항을 볼 수 없음을 의미합니다.

그러나 여러 스레드의 범위 내에 있는 변수에 액세스하려면 Mutex 및 Lock과 같은 기술을 조사해야 합니다. 스레드 잠금은 값이 사용되는 동안 수정되는 것을 방지하는 간단한 구성입니다. Powershell에서는 $using:더 높은 범위의 변수를 참조하기 위한 키워드를 추가하여 이를 쉽게 만들었습니다 .

자세한 내용은 여기를 참조하세요.https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

관련 정보