在使用 Start-ThreadJob 启动的线程中修改 PowerShell $using 范围变量

Modifying PowerShell $using scope variables in thread started with Start-ThreadJob

如果我理解 PowerShell Scopes documentation,应该可以从使用 Start-ThreadJob 开始的线程分配给 $using 范围变量。文档说(强调我的):

The Using scope modifier is supported in the following contexts:

  • ...
  • Thread jobs, started via Start-ThreadJob or ForEach-Object -Parallel (separate thread session)

Depending on the context, embedded variable values are either independent copies of the data in the caller's scope or references to it.
...
In thread sessions, they are passed by reference. This means it is possible to modify call scope variables in a different thread. To safely modify variables requires thread synchronization.

但以下内容无法 运行:

$foo = 1

Start-ThreadJob {
    Write-Host $using:foo
    $using:foo = 2
} | Wait-Job | Out-Null

Write-Host $foo

它在 $using:foo = 2 上出错:

The assignment expression is not valid. The input to an assignment operator must be an object that is able to accept assignments, such as a variable or a property.

使用 Write-Host $using:foo 打印变量工作正常。

我正在使用 PowerShell 7.1。

您不能覆盖 $using: 变量引用 - 但您可以使用它来取消引用调用范围中的变量值,此时您可以改变它(假设引用类型值是分配给原始变量):

$foo = @{ 
  Value = 1
}
Start-ThreadJob {
    Write-Host $using:foo
    $foo = $using:foo
    $foo.Value = 2
} | Wait-Job | Out-Null

Write-Host $foo.Value

为确保线程同步,我建议将同步哈希表作为您的容器类型:

$foo = [hashtable]::Synchronized(@{ 
  Value = 1
})

1..4 |%{Start-ThreadJob {
    Write-Host $using:foo
    $foo = $using:foo
    $foo.Value++
}} | Wait-Job | Out-Null

Write-Host $foo.Value

此时您应该看到 5

的(增加 4 倍)值