首页 > 解决方案 > 我的 Powershell 脚本不做多线程工作,为什么?

问题描述

#my script 是https://www.codeproject.com/Tips/895840/Multi-Threaded-PowerShell-Cookbook的摘录 #the first example #the issue is where ".AddScript($secb)" is. 所有的工作都是按顺序完成的,谁能解释一下???#为什么在我的脚本中,.AddScript($sb) 是并发的?



$numThreads = 5
# Create session state
$myString = "this is session state!"
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$sessionstate.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList "myString" ,$myString, "example string"))
   
# Create runspace pool consisting of $numThreads runspaces
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 5, $sessionState, $Host)
$RunspacePool.Open()

$Jobs = @()
$sb={
param ($data)
$r=Get-Random
Write-Host "before $r"
Start-Sleep -Seconds 3
Write-Host "after $r"
}
$secb={
param ($block)
Invoke-Command -ScriptBlock $block
}
1..5 | % {
    #below line is not concurrent  , i don't know why
    $Job = [powershell]::Create().AddScript($secb) # $Job = [powershell]::Create().AddScript($sb) could do multi-thread
    $Job.AddArgument($sb)

    $Job.RunspacePool = $RunspacePool
    $Jobs += New-Object PSObject -Property @{
      RunNum = $_
      Job = $Job
      Result = $Job.BeginInvoke()
   }
}
 
Write-Host "Waiting.." -NoNewline
Do {
   Write-Host "." -NoNewline
   Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false) #Jobs.Result is a collection

标签: powershell

解决方案


到目前为止,我还不是专家RunSpaces,通常每当我需要多线程时,我都会使用该ThreadJob模块。我不确定您在代码中做错了什么,但我可以向您展示您正在尝试做的工作示例。我从这个答案(感谢 Mathias)中拿了这个例子,这个例子非常好,并做了一些修改。

代码:

cls
$elapsedTime = [System.Diagnostics.Stopwatch]::StartNew()

$numThreads = 5
# Create session state
$myString = "this is session state!"
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$sessionstate.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList "myString" ,$myString, "example string"))
   
# Create runspace pool consisting of $numThreads runspaces
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 5, $sessionState, $Host)
$RunspacePool.Open()

$runspaces = foreach($i in 1..5)
{
    $PSInstance = [powershell]::Create().AddScript({
        param ($TestNumber)

        Write-Output "Test Number: $TestNumber"

        $r={Get-Random}

        Write-Output "before $(& $r)"
        Start-Sleep -Seconds 3
        Write-Output "after $(& $r)"

    }).AddParameter('TestNumber',$i)

    $PSInstance.RunspacePool = $RunspacePool

    [pscustomobject]@{
        Instance = $PSInstance
        Result = $PSInstance.BeginInvoke()
    }
}
 
while($runspaces|Where-Object{-not $_.Result.IsCompleted})
{
    Start-Sleep -Milliseconds 500
}

$resultRunspace = [collections.generic.list[string]]::new()

$Runspaces|ForEach-Object {
    $resultRunspace.Add($_.Instance.EndInvoke($_.Result))
}

$elapsedTime.Stop()
"Elapsed Time: {0}" -f $elapsedTime.Elapsed.TotalSeconds
""
$resultRunspace

结果:

Elapsed Time: 3.1271587

Test Number: 1 before 474010429 after 2055432874
Test Number: 2 before 1639634857 after 1049683678
Test Number: 3 before 72786850 after 2046654322
Test Number: 4 before 1958738687 after 1832326064
Test Number: 5 before 1944958392 after 1652518661

现在,再次,如果您能够安装模块,我会推荐ThreadJob它,因为它更易于使用并且执行速度与RunSpaces.

前段时间我写了一个脚本,它将遍历所有目录$HOME并获取每个目录的文件数,该脚本旨在比较Linear Loopsvs ThreadJobvsRunSpace这里的结果以及为什么我总是推荐ThreadJob

在此处输入图像描述


推荐阅读