PowerShell:脚本并行抛出

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:\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/

相关内容