2

PowerShell Scopesのドキュメントを理解していれば、$usingを使用して開始されたスレッドからスコープ変数に割り当てることができるはずStart-ThreadJobです。ドキュメントには次のように書かれています(強調鉱山):

Usingスコープ修飾子は、次のコンテキストでサポートされています。

  • ...
  • Start-ThreadJobまたはForEach-Object -Parallel(別のスレッド セッション)を介して開始されたスレッド ジョブ

コンテキストに応じて、埋め込み変数の値は、呼び出し元のスコープ内のデータの独立したコピーか、それへの参照のいずれかになります。
...
スレッド セッションでは、参照によって渡されます。これは、別のスレッドで呼び出しスコープ変数を変更できることを意味します。変数を安全に変更するには、スレッドの同期が必要です。

それでも、以下は実行に失敗します:

$foo = 1

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

Write-Host $foo

次のエラーが発生$using:foo = 2します。

代入式が無効です。代入演算子への入力は、変数やプロパティなど、代入を受け入れることができるオブジェクトでなければなりません。

変数の印刷はWrite-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 に答える