Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我的Powershell脚本没有';我不能做多线程的工作,为什么?_Powershell - Fatal编程技术网

我的Powershell脚本没有';我不能做多线程的工作,为什么?

我的Powershell脚本没有';我不能做多线程的工作,为什么?,powershell,Powershell,#我的剧本摘自 #第一个例子 #问题是“.AddScript($secb)”在哪里。所有的工作都是按顺序完成的,有人能解释一下吗??? #为什么在我的脚本中,.AddScript($sb)是并发的 $numThreads = 5 # Create session state $myString = "this is session state!" $sessionState = [System.Management.Automation.Runspaces.Initial

#我的剧本摘自 #第一个例子 #问题是“.AddScript($secb)”在哪里。所有的工作都是按顺序完成的,有人能解释一下吗??? #为什么在我的脚本中,.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


到目前为止,我还不是运行空间方面的专家,通常每当我需要多线程时,我都会使用
ThreadJob
模块。我不确定您在代码中犯了什么错误,但我可以为您展示一个工作示例,说明您正在尝试做什么。我从(Mathias的学分)中选取了这个例子,它非常优秀,并对它进行了一些修改

代码: 结果: 现在,同样,如果您能够安装模块,我建议您使用
ThreadJob
,因为它比
RunSpaces
更易于使用,执行速度也同样快

不久前我写了一个脚本,它将遍历
$HOME
中的所有目录,并获取每个目录上的文件数,该脚本旨在比较
线性循环与
线程作业
运行空间
以下是结果,以及为什么我总是推荐
线程作业


如果您能安装模块,我绝对推荐。它的速度和运行空间一样快,使用起来也更简单。或者在powershell 7中使用foreach对象-并行。@js2010实际上我很想看看foreach对象-并行与ThreadJob和运行空间的性能如何。我有一个用于
ThreadJob
vs
RunSpace
vs
Linear Loop
。谢谢你们,你们太好了!!我使用运行空间的原因是因为环境失控,我唯一能保证的是它们都是PS5.1Thanks Santiago,我想尝试一下,但是,我必须在其他机器上运行脚本,这是失控的。而我必须雇用runspace@HMarcus这里有一个工作运行空间的示例,您只需要更改
.AddScript({})
块中的内容,并确保它返回您所需的输出(这就是为什么我将示例中的
Write Host
更改为
Write output
)。
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