Multithreading Powershell:来自多个线程的增量变量
在Powershell中,是否有一种方法可以安全地从多个线程中递增变量 我认为下面使用Multithreading Powershell:来自多个线程的增量变量,multithreading,powershell,Multithreading,Powershell,在Powershell中,是否有一种方法可以安全地从多个线程中递增变量 我认为下面使用System.Threading.Interlock::Add的代码可以工作,但输出显示正在发生线程混搭 # Threads will attempt to increment this number $testNumber = 0 # Script will increment the test number 10 times $script = { Param( [ref]$te
System.Threading.Interlock::Add
的代码可以工作,但输出显示正在发生线程混搭
# Threads will attempt to increment this number
$testNumber = 0
# Script will increment the test number 10 times
$script = {
Param(
[ref]$testNumber
)
1..10 | % {
[System.Threading.Interlocked]::Add($testNumber, 1) | Out-Null
}
}
# Start 10 threads to increment the same number
$threads = @()
1..10 | % {
$ps = [powershell]::Create()
$ps.AddScript($script) | Out-Null
$ps.RunspacePool = $pool
$ps.AddParameter('testNumber', [ref]$testNumber) | Out-Null
$threads += @{
ps = $ps
handle = $ps.BeginInvoke()
}
}
# Wait for threads to complete
while ($threads | ? {!$_.Handle.IsCompleted }) {
Start-Sleep -Milliseconds 100
}
# Print the output (should be 100=10*10, but is between 90 and 100)
echo $testNumber
正如在注释中一样,您需要使用同步哈希表跨运行空间边界读写数据(请参阅内联注释以获取解释):
我请求您需要创建一个同步哈希表,例如:
[hashtable]::synchronized(@{TestNumber=0})
,请参阅例如:$pool
是未定义的变量。复制粘贴错误?
# Threads will attempt to increment this number
$testNumber = 0
# Create synchronized hashtable to act as gatekeeper
$syncHash = [hashtable]::Synchronized(@{ testNumber = $testNumber })
# Create runspace pool with a proxy variable mapping back to $syncHash
$iss = [initialsessionstate]::CreateDefault2()
$iss.Variables.Add(
[System.Management.Automation.Runspaces.SessionStateVariableEntry]::new('syncHash', $syncHash,'')
)
$pool = [runspacefactory]::CreateRunspacePool($iss)
$pool.Open()
# Script will increment the test number 10 times
$script = {
Param(
[string]$targetValue
)
1..10 | % {
# We no longer need Interlocked.* and hairy [ref]-casts, $syncHash is already thread safe
$syncHash[$targetValue]++
}
}
# Start 10 threads to increment the same number
$threads = @()
1..10 | % {
$ps = [powershell]::Create()
$ps.AddScript($script) | Out-Null
$ps.RunspacePool = $pool
# We're no longer passing a [ref] to the variable in the calling runspace.
# Instead, we target the syncHash entry by name
$ps.AddParameter('targetValue', 'testNumber') | Out-Null
$threads += @{
ps = $ps
handle = $ps.BeginInvoke()
}
}
# Wait for threads to complete
while ($threads | ? {!$_.Handle.IsCompleted }) {
Start-Sleep -Milliseconds 100
}
$errorCount = 0
# End invocation lifecycle
$threads|%{
if($_.ps.HadErrors){
$errorCount++
}
$_.ps.EndInvoke($_.handle)
}
if($errorCount){
Write-Warning "${errorCount} thread$(if($errorCount -gt 1){'s'}) had errors"
}
# Et voila, $syncHash['testNumber'] is now 100
$syncHash['testNumber']