- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 for
循环,它遍历 ArrayList
并在此过程中向列表添加更多项目并(迭代地)处理它们。我正在尝试使用 Runspacepool 将此函数转换为同时运行。
这是没有运行空间的正常代码:
$array = [System.Collections.ArrayList]@(1, 2, 3, 4, 5)
Write-Host "Number of items in array before loop: $($array.Count)"
for ($i = 0; $i -lt $array.Count; $i++) {
Write-Host "Counter: $i`tArray: $array"
if ($array[$i] -in @(1, 2, 3, 4, 5)) {
$array.Add($array[$i] + 3) | Out-Null
}
}
Write-Host "Array: $array"
Write-Host "Number of items in array after loop: $($array.Count)"
输出是:
Number of items in array before loop: 5
Counter: 0 Array: 1 2 3 4 5
Counter: 1 Array: 1 2 3 4 5 4
Counter: 2 Array: 1 2 3 4 5 4 5
Counter: 3 Array: 1 2 3 4 5 4 5 6
Counter: 4 Array: 1 2 3 4 5 4 5 6 7
Counter: 5 Array: 1 2 3 4 5 4 5 6 7 8
Counter: 6 Array: 1 2 3 4 5 4 5 6 7 8 7
Counter: 7 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Counter: 8 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Counter: 9 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Counter: 10 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Counter: 11 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Array: 1 2 3 4 5 4 5 6 7 8 7 8
Number of items in array after loop: 12
这是 Runspace function我正在尝试实现:
$pool = [RunspaceFactory]::CreateRunspacePool(1, 10)
$pool.Open()
$runspaces = @()
$scriptblock = {
Param ($i, $array)
# Start-Sleep 1 # <------ Output varies significantly if this is enabled
Write-Output "$i value: $array"
if ($i -in @(1, 2, 3, 4, 5)) {
$array.Add($i + 3) | Out-Null
}
}
$array = [System.Collections.ArrayList]::Synchronized(([System.Collections.ArrayList]$(1, 2, 3, 4, 5)))
Write-Host "Number of items in array before loop: $($array.Count)"
for ($i = 0; $i -lt $array.Count; $i++) {
$runspace = [PowerShell]::Create().AddScript($scriptblock).AddArgument($array[$i]).AddArgument($array)
$runspace.RunspacePool = $pool
$runspaces += [PSCustomObject]@{ Pipe = $runspace; Status = $runspace.BeginInvoke() }
}
while ($runspaces.Status -ne $null) {
$completed = $runspaces | Where-Object { $_.Status.IsCompleted -eq $true }
foreach ($runspace in $completed) {
$runspace.Pipe.EndInvoke($runspace.Status)
$runspace.Status = $null
}
}
Write-Host "array: $array"
Write-Host "Number of items in array after loop: $($array.Count)"
$pool.Close()
$pool.Dispose()
没有 sleep 功能的输出符合预期:
Number of items in array before loop: 5
Current value: 1 Array: 1 2 3 4 5
Current value: 2 Array: 1 2 3 4 5 4
Current value: 3 Array: 1 2 3 4 5 4 5
Current value: 4 Array: 1 2 3 4 5 4 5 6
Current value: 5 Array: 1 2 3 4 5 4 5 6 7
Current value: 4 Array: 1 2 3 4 5 4 5 6 7 8
Current value: 5 Array: 1 2 3 4 5 4 5 6 7 8 7
Current value: 6 Array: 1 2 3 4 5 4 5 6 7 8 7
Current value: 7 Array: 1 2 3 4 5 4 5 6 7 8 7
Current value: 8 Array: 1 2 3 4 5 4 5 6 7 8 7
Current value: 7 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Current value: 8 Array: 1 2 3 4 5 4 5 6 7 8 7 8
Array: 1 2 3 4 5 4 5 6 7 8 7 8
Number of items in array after loop: 12
sleep 输出:
Number of items in array before loop: 5
Current value: 1 Array: 1 2 3 4 5
Current value: 2 Array: 1 2 3 4 5 4
Current value: 3 Array: 1 2 3 4 5 4 5
Current value: 4 Array: 1 2 3 4 5 4 5 6
Current value: 5 Array: 1 2 3 4 5 4 5 6 7
Array: 1 2 3 4 5 4 5 6 7 8
Number of items in array after loop: 10
我知道发生这种情况是因为 for
循环在 sleep 时间完成之前退出,因此只有前 5 个项目被添加到运行空间池中。
有没有办法动态地向 ArrayList 添加更多项,并且仍然使用运行空间并发处理它们?
最佳答案
您“工作”行为的核心是 PowerShell 运行您的“非 sleep ”脚本 block 的速度快于它在 for
中创建它们的速度循环,所以循环看到在到达数组末尾之前由先前迭代添加的新项目。结果,它必须在退出并移至 while
之前处理所有 项。循环。
当您添加 Start-Sleep
它改变了平衡,运行脚本 block 比创建脚本 block 花费的时间更长,所以for
在最早的迭代添加新项之前,循环已到达数组末尾。
以下脚本通过结合您的 for
解决了这个问题和 while
循环在 (i) 创建新线程和 (ii) 检查它们是否已完成之间反复交替,并且仅在所有工作完成时退出。
但是多线程很难,所以最好假设我在某处犯了错误,并在将其发布到您的实时工作流程之前进行正确测试...
$scriptblock = {
Param ($i, $array)
# random sleep to simulate variable-length workloads. this is
# more likely to flush out error conditions than a fixed sleep
# period as threads will finish out-of-turn more often
Start-Sleep (Get-Random -Minimum 1 -Maximum 10)
Write-Output "$i value: $array"
if ($i -in @(1, 2, 3, 4, 5)) {
$array.Add($i + 3) | Out-Null
}
}
$pool = [RunspaceFactory]::CreateRunspacePool(1, 10)
$pool.Open()
# note - your "$runspaces" variable is misleading as you're creating
# "PowerShell" objects, and a "Runspace" is a different thing entirely,
# so I've called it $instances instead
# see https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.powershell?view=powershellsdk-7.0.0
# vs https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspace?view=powershellsdk-7.0.0
$instances = @()
$array = [System.Collections.ArrayList]::Synchronized(([System.Collections.ArrayList]$(1, 2, 3, 4, 5)))
Write-Host "Number of items in array before loop: $($array.Count)"
while( $true )
{
# start PowerShell instances for any items in $array that don't already have one.
# on the first iteration this will seed the initial instances, and in
# subsequent iterations it will create new instances for items added to
# $array since the last iteration.
while( $instances.Length -lt $array.Count )
{
$instance = [PowerShell]::Create().AddScript($scriptblock).AddArgument($array[$instances.Length]).AddArgument($array);
$instance.RunspacePool = $pool
$instances += [PSCustomObject]@{ Value = $instance; Status = $instance.BeginInvoke() }
}
# watch out because there's a race condition here. it'll need very unlucky
# timing, *but* an instance might have added an item to $array just after
# the while loop finished, but before the next line runs, so there *could*
# be an item in $array that hasn't had an instance created for it even
# if all the current instances have completed
# is there any more work to do? (try to mitigate the race condition
# by checking again for any items in $array that don't have an instance
# created for them)
$active = @( $instances | Where-Object { -not $_.Status.IsCompleted } )
if( ($active.Length -eq 0) -and ($instances.Length -eq $array.Count) )
{
# instances have been created for every item in $array,
# *and* they've run to completion, so there's no more work to do
break;
}
# if there are incomplete instances, wait for a short time to let them run
# (this is to avoid a "busy wait" - https://en.wikipedia.org/wiki/Busy_waiting)
Start-Sleep -Milliseconds 250;
}
# all the instances have completed, so end them
foreach ($instance in $instances)
{
$instance.Value.EndInvoke($instance.Status);
}
Write-Host "array: $array"
Write-Host "Number of items in array after loop: $($array.Count)"
$pool.Close()
$pool.Dispose()
示例输出:
Number of items in array before loop: 5
1 value: 1 2 3 4 5 6 5 7
2 value: 1 2 3 4 5 6
3 value: 1 2 3 4 5
4 value: 1 2 3 4 5 6 5
5 value: 1 2 3 4 5 6 5 7 4
6 value: 1 2 3 4 5 6 5 7
5 value: 1 2 3 4 5 6 5 7 4 8
7 value: 1 2 3 4 5 6 5 7
4 value: 1 2 3 4 5 6 5 7 4 8 8
8 value: 1 2 3 4 5 6 5 7 4 8 8
8 value: 1 2 3 4 5 6 5 7 4 8 8
7 value: 1 2 3 4 5 6 5 7 4 8 8 7
请注意,数组中项目的顺序将根据 $scriptblock
中随机 sleep 的长度而变化。 .
可能还可以进行其他改进,但这至少看起来可行...
关于powershell - 如何将项目动态添加到 PowerShell ArrayList 并使用运行空间池递归处理它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72725891/
我正在寻找实现 PowerShell 提供程序 在 电源外壳。 我一直在想,如果我只是定义类型,然后将它们导入我的 session (导入模块),我应该能够让它们可用。 例如,这个 不工作但它沿着我想
我创建的脚本使用了组件,这些组件仅在32位版本的Powershell中可用。 默认情况下,Windows使用Powershell x64执行脚本,这会导致一些错误。 是一种在脚本开头设置值以强制Win
是否可以从 Powershell 中检测它是否是嵌套 shell? 如果我打开 Powershell 或 cmd.exe 窗口,然后输入 powershell 在那里,是否有一个神奇的 $host.s
随着 PowerShell Core 的发布,应用程序在使用托管自动化库 (system.management.automation) 时如何选择调用哪个版本的 Powershell(Powershe
最近,我加入了我企业的 Windows 团队,凭借我的开发人员背景(一般是 Java、.NET 和 Web),我很快就对 PowerShell 产生了兴趣。我可以看到它比普通的旧批处理文件、VB 更有
假设我有一个 powershell 脚本,它在我当前路径的相对路径中包含一个 Powershell 哈希。让我们称之为“name.ps1”,它包含: $names = @{ "bob" = "b
我想为我正在构建的自定义 Powershell Commandlet 使用 SqlServerCmdletSnapin。如果我将以下代码添加到 PSM1 的开头: if ( (Get-PSSnapin
如何调用从 PowerShell 脚本中获取命名参数的 PowerShell 脚本? foo.ps1: param( [Parameter(Mandatory=$true)][String]$a=''
我即将为 Windows 管理员编写一个 PowerShell 脚本,以帮助他们完成与部署 Web 应用程序相关的某些任务。 有什么理由让我应该赞成或排除开发 PowerShell 模块 (.psm1
我的 powershell 模块有一个函数,我希望它返回一个非零退出代码。但是,作为一个模块函数,当我运行 Import-Module 时,它会加载到 powershell 控制台的上下文中。所以,当
我在这个问题上花了最后 4 个小时,非常感谢您提供的任何意见。 我需要使用不同的凭据调用 powershell 脚本并将参数传递给该脚本。 安装 WISEScript 中包装的程序后,此脚本开始收集机
我有一个场景,我需要将 powershell 命令的命令和输出转发到另一个进程以进行日志记录和处理。 我希望这个控制台尽可能接近 powershell,因此不希望将它简单地托管在另一个控制台程序中。
我正在尝试让一个主 PowerShell 脚本运行所有其他脚本,同时等待 30-60 秒以确保完成任务。我尝试过的所有其他操作都不会停止/等待第一个脚本及其进程完成,然后才能同时完成所有其他脚本,并且
我正在编写一个脚本来使用多个 plink (PuTTY) session 作为 Windows 版本的 clustersh。然而,我陷入困境,因为我想从 powershell 打开多个 Powersh
我读了这个答案:How to Open Powershell from Powershell start powershell 这将打开基础的大分辨率 PS 实例。如何打开 PS(x86)? 最佳答案
我很想知道我们是否可以在 Powershell 中做到这一点。 使用 Out-File 命令,我们可以通过管道将其输出写入文件。这样我就可以将我所有的历史命令发送到一个文本文件中。 问题是我可以在每次
我在 about_Pipelines 阅读了有关 PowerShell 中的管道工作原理的信息,并了解到管道一次传送一个对象。 所以,这个 Get-Service | Format-Table -Pr
我正在尝试像这样从 powershell 启动一个进程:- $proc = (start-process $myExe -argumentList '/myArg True' -windowStyle
## To run the script # .\get_status.ps1 -Hostname -Service_Action -Service_Name #$Hostname = "hos
让我们使用 powershell 命令 Write-Host "red text"-Fore red这会在红色前景中显示“红色文本”。 但是,您希望文本以稍微亮一点的方式显示字体颜色,浅红色。 有没有
我是一名优秀的程序员,十分优秀!