You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 5中BeginInvoke<TInput,TOutput>重载的输入参数传递问题

PowerShell 5 并行处理中 BeginInvoke<TInput,TOutput> 输入传递问题解决

核心错误分析

  • 参数类型定义错误:BeginInvoke 的 $Inputs 集合中的单个元素会作为管道输入传递给脚本块,而非整个 PSDataCollection 集合。因此脚本块参数不应定义为 [System.Management.Automation.PSDataCollection],而是对应集合中元素的类型(这里是 PSObject 或自定义对象)。
  • 管道输入处理缺失:使用 ValueFromPipeline 时,脚本块需要通过 process 块来处理管道输入(PowerShell 脚本块默认只在 end 块执行,无法接收管道传递的单个元素)。
  • 取值逻辑错误:脚本块中无需通过 $Bias[0] 取值,因为参数已经接收的是 $Inputs 中的单个对象。

修正后的代码

$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 5)
$RunspacePool.Open()

$Inputs  = New-Object 'System.Management.Automation.PSDataCollection[PSObject]'
$Outputs = New-Object 'System.Management.Automation.PSDataCollection[PSObject]'

# 添加输入元素
$Inputs.Add([PSCustomObject]@{ Bias = 100 })

$ScriptBlock = { 
    Param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [PSObject]$InputObject  # 接收单个输入元素
    )
    # 使用process块处理管道输入
    process {
        (Get-Random -Maximum 100) + $InputObject.Bias
    }
}

$Instances = (1..10) | ForEach-Object {
    $Instance = [powershell]::Create().AddScript($ScriptBlock)
    $Instance.RunspacePool = $RunspacePool
    [PSCustomObject]@{
        Instance = $Instance
        State = $Instance.BeginInvoke($Inputs,$Outputs)
    }
}

# 等待所有线程完成
while ($Instances.State.IsCompleted -contains $False) { 
    Start-Sleep -Milliseconds 100 
}

# 输出结果
$Outputs

关键原理说明

  • BeginInvoke<TInput,TOutput> 的 $Inputs 参数本质是管道输入数据源:脚本块会以管道处理的方式逐个接收集合中的元素,而非一次性获取整个集合。
  • 当你创建多个 [powershell] 实例并关联同一个 $Inputs 时,每个实例都会独立处理整个 $Inputs 集合中的元素(因此你会得到10个结果,每个都是随机数+100)。
  • 如果需要让不同实例处理 $Inputs 中的不同元素,可以在 $Inputs 中添加多个元素,PowerShell 会自动将元素分配给空闲的 runspace 实例。

内容的提问来源于stack exchange,提问作者Newtown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:54:52