PowerShell: Skript wird parallel abgebrochen

PowerShell: Skript wird parallel abgebrochen

Wenn -Paralleldas folgende Skript in ausgeführt wird, übergibt es die $basePathvor dem Start des parallelen Blocks deklarierte Variable nicht. Stattdessen ist es ein Nullwert. Dies ist kein Problem, wenn das Skript nicht in ausgeführt wird -Parallel– es übergibt den Variablenwert und wird wie erwartet ausgeführt. Zu Ihrer Information: Ich verwende 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"

Antwort1

-parallelDaher müssen Sie im neuen Schema von Powershell für alle Aufrufe innerhalb der parallelen Schleife $using:basePathanstelle von nur verwenden $basePath. Dies liegt daran, dass die Variable in einem übergeordneten Bereich definiert ist.

Multithreading und parallele Operationen bringen eine Reihe einzigartiger Komplikationen mit sich, die zusammenfassend als Parallelitäts- oder Multi-Parallelitätsprobleme bezeichnet werden. Daher sind spezielle Schritte erforderlich, um sicherzustellen, dass der von den Threads aufgerufene Speicher sich in einem sicheren Nutzungszustand befindet.

Powershell implementiert einen Threadkontext namens RunSpace und erstellt einen für jeden parallelen Vorgang. Der Runspace enthält eine Kopie jeder in diesem Block deklarierten Variable und kann nur mit diesen kopierten Instanzen der Variablen arbeiten. Dies bedeutet, dass, wenn ein Thread seine Version der Variable ändert, andere Threads diese Änderung nicht sehen.

Um jedoch auf eine Variable zuzugreifen, die für mehrere Threads gültig ist, müssen wir uns Techniken wie Mutex und Sperren ansehen. Eine Threadsperre ist eine einfache Konstruktion, die verhindert, dass ein Wert während der Verwendung geändert wird. In Powershell wurde dies vereinfacht, indem das $using:Schlüsselwort zum Verweisen auf Variablen mit höherem Gültigkeitsbereich hinzugefügt wurde.

Weitere Einzelheiten finden Sie hier:https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

verwandte Informationen