我发现的所有内容都使用预定义的睡眠时间来限制作业。 我需要油门等到工作完成后再开始新工作。 一次只能运行4个作业。
因此脚本将运行4并且当前暂停10秒然后运行其余部分。 我想要的是脚本只允许一次运行4个作业,并且在作业完成后,新的作业将被启动。
通过服务器名称列表初始化作业。
是否可以存档?
$servers = Get-Content "C:\temp\flashfilestore\serverlist.txt"
$scriptBlock = { #DO STUFF }
$MaxThreads = 4
foreach($server in $servers) {
Start-Job -ScriptBlock $scriptBlock -argumentlist $server
While($(Get-Job -State 'Running').Count -ge $MaxThreads) {
sleep 10 #Need this to wait until a job is complete and kick off a new one.
}
}
Get-Job | Wait-Job | Receive-Job
答案 0 :(得分:4)
您可以测试以下内容:
$servers = Get-Content "C:\temp\flashfilestore\serverlist.txt"
$scriptBlock = { #DO STUFF }
invoke-command -computerName $servers -scriptblock $scriptBlock -jobname 'YourJobSpecificName' -throttlelimit 4 -AsJob
此命令使用Invoke-Command cmdlet及其AsJob参数来启动在多台计算机上运行scriptblock的后台作业。由于该命令不能同时运行4次以上,因此该命令使用Invoke-Command的ThrottleLimit参数将并发命令的数量限制为4。
请注意,该文件包含域中的计算机名称。
答案 1 :(得分:4)
为了避免发明轮子,我建议使用其中一个 现有工具。
其中一个是脚本 Invoke-Parallel.ps1。 它是用PowerShell编写的,你可以看到它是如何直接实现的。它是 容易获得,并且不需要任何安装即可使用它。
另一个是模块SplitPipeline。 它可能更快,因为它是用C#编写的。它还包括更多用途 例如,缓慢或无限输入,使用初始化和清理脚本。
在后一种情况下,具有4个并行流水线的代码将是
$servers | Split-Pipeline -Count 4 {process{ <# DO STUFF on $_ #> }}
答案 2 :(得分:2)
我写了一篇博客文章,其中涵盖了通过实际线程对任何给定脚本进行多线程处理。你可以在这里找到完整的帖子:
http://www.get-blog.com/?p=189
基本设置是:
$ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
$RunspacePool.Open()
$Code = [ScriptBlock]::Create($(Get-Content $FileName))
$PowershellThread = [powershell]::Create().AddScript($Code)
$PowershellThread.RunspacePool = $RunspacePool
$Handle = $PowershellThread.BeginInvoke()
$Job = "" | Select-Object Handle, Thread, object
$Job.Handle = $Handle
$Job.Thread = $PowershellThread
$Job.Object = $Object.ToString()
$Job.Thread.EndInvoke($Job.Handle)
$Job.Thread.Dispose()
答案 3 :(得分:1)
而不是sleep 10
你也可以等待工作(-any
工作):
Get-Job | Wait-Job -Any | Out-Null
当没有更多作业开始时,开始打印输出。您也可以在上述命令后立即在循环内执行此操作。该脚本将在完成后接收作业,而不是等到结束。
Get-Job -State Completed | % {
Receive-Job $_ -AutoRemoveJob -Wait
}
所以你的脚本看起来像这样:
$servers = Get-Content "C:\temp\flashfilestore\serverlist.txt"
$scriptBlock = { #DO STUFF }
$MaxThreads = 4
foreach ($server in $servers) {
Start-Job -ScriptBlock $scriptBlock -argumentlist $server
While($(Get-Job -State Running).Count -ge $MaxThreads) {
Get-Job | Wait-Job -Any | Out-Null
}
Get-Job -State Completed | % {
Receive-Job $_ -AutoRemoveJob -Wait
}
}
While ($(Get-Job -State Running).Count -gt 0) {
Get-Job | Wait-Job -Any | Out-Null
}
Get-Job -State Completed | % {
Receive-Job $_ -AutoRemoveJob -Wait
}
说了这么多,我更喜欢运行空间(类似于Ryans帖子)甚至工作流程,如果你可以使用它们。这些资源比开始多个PowerShell流程要少得多。
答案 4 :(得分:0)
您的脚本看起来不错,请尝试添加类似
的内容 Write-Host ("current count:" + ($(Get-Job -State 'Running').Count) + " on server:" + $server)
计算出你的工作量是否会下降到你不期望的地方。
答案 5 :(得分:0)
我注意到每个Start-Job命令都在任务管理器中导致了一个额外的 public void addSeller(Seller seller){
HashMap<String,Seller> map= new HashMap<>() ;
String email = seller.getEmail().replace(".",",");
map.put(email,seler);
database.child("sellers").setValue(map);
}
进程。知道这一点,我能够使用以下逻辑进行限制,其中conhost.exe
是我所需的并发线程数(因此我在5
语句中使用4
,因为我正在寻找一个计数大于):
-gt