2

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

在以下Using上下文中支持范围修饰符:

  • ...
  • 线程作业,通过Start-ThreadJobForEach-Object -Parallel(单独的线程会话)启动

根据上下文,嵌入的变量值要么是调用者范围内数据的独立副本,要么是对其的引用
...
在线程会话中,它们通过引用传递。这意味着可以在不同的线程中修改调用范围变量。安全地修改变量需要线程同步。

然而以下无法运行:

$foo = 1

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

Write-Host $foo

它错误$using:foo = 2

赋值表达式无效。赋值运算符的输入必须是能够接受赋值的对象,例如变量或属性。

打印变量 withWrite-Host $using:foo可以正常工作。

我正在使用 PowerShell 7.1。

4

1 回答 1

2

您不能覆盖$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

此时您应该会看到(4 倍递增)的值5

于 2021-03-24T15:48:18.000 回答