
當在 中執行時-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 的執行緒上下文,並為每個平行操作建立一個執行緒上下文。運行空間包含該區塊中聲明的每個變數的副本,並且只能對這些變數的複製實例進行操作。這意味著如果一個線程修改了變數的版本,其他線程將看不到這一變化。
然而,為了存取多個執行緒範圍內的變量,我們必須研究諸如互斥鎖和鎖之類的技術。線程鎖是一種簡單的構造,可防止值在使用時被修改。在 Powershell 中,他們透過添加$using:
關鍵字來引用更高範圍的變量,使這變得簡單。
請參閱此處以了解更多詳細資訊:https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/