Powershell 作业执行可以正确处理批处理,而无需等待整个批处理完成

Powershell job execution handle batch processing properly without waiting for whole batch to finish

我正在使用 PowerShell 作业并行处理 activity。我在下面附上了它的示例代码。

Function Wait-UntilJobFailOrSuccess {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [System.Management.Automation.Job[]]$Job
    )
    begin {
        $jobs = @()
        $abort = $false
    }
    process {
        $jobs += $Job
    }
    end {

        while ('Running' -In $jobs.State) {
            if ('Failed' -in $jobs.State) {
                $jobs | Stop-Job 
                $abort = $true
                break
            }
            Start-Sleep -Milliseconds 500
        }

        foreach ($job in $jobs) {
            if ($job.State -eq 'Failed') {
                $job.ChildJobs | ForEach-Object {
                    Write-Host ($_.JobStateInfo.Reason.Message) -ForegroundColor Red
                }
            }
            else {

                Write-Host "$($job.Name) $($job.State) successfully"
            }
        }

        if ($abort) {
            exit 1
        }
    }
}

以上方法将用于并行执行的作业。

$packageSpecs | ForEach-Object -Begin {
    $job = @()
} -Process {
    $builditem = $_ 
   $job += Start-Job -Name $("Pack" + $builditem.name) -ScriptBlock $scriptoExecute -ArgumentList $args
    if ($job.Count -eq $maxNumberOfThread) {
        $job |Wait-UntilJobFailOrSuccess
        $job = @()
    }
} -End {

    if ($job.Count -gt 0) {
        $job |Wait-UntilJobFailOrSuccess
        $job = @()
    }

}

如果您看到上面的代码,我 运行 作业基于机器中 CPU 的数量,$maxNumberOfThread 包含系统中允许的逻辑进程数。

现在我会告诉你我的问题陈述。

假设 $maxNumberOfThread =4。它将一次处理 4 个作业。我想要的是如果我正在处理 4 个工作并且任何工作都已完成。我应该可以排队下一个。目前它正在处理所有 4 个作业,然后是下一批。

我做了一些调整,删除了 Wait-UntilJobFailOrSuccess 函数。但这应该有效。试试让我知道。如果它有效,那么你可以根据你的功能调整它。

 $packageSpecs | ForEach-Object -Begin {
     $job = @()
 } -Process {
     $builditem = $_ 
     $job += Start-Job -Name $("Pack" + $builditem.name) -ScriptBlock $scriptoExecute -ArgumentList $args
     $running = @($job | Where-Object { $_.State -eq 'Running' })
     if ($running.Count -ge $maxNumberOfThread) {
         $running | Wait-Job -Any | Out-Null
         Write-Verbose "Waiting on jobs" -Verbose
     }  

 } -End {

     if ($job.Count -gt 0) {
         $job |Wait-UntilJobFailOrSuccess
         $job = @()
     }
 }

我对你的函数做了一些修改,请告诉我它是如何工作的。该函数现在需要传递给它的 $MaxNumberOfThread。

Function Wait-UntilJobFailOrSuccess {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [System.Management.Automation.Job[]]$Job,

        [Parameter()]
        [int]$maxNumberOfThread
    )
    begin {
        $jobs = @()
        $abort = $false
    }
    process {
        $jobs += $Job
        foreach ($j in $Jobs) {
            $running = @($jobs | Where-Object { $_.State -eq 'Running' })
            if ($running.Count -ge $maxNumberOfThread) {
                if ('Failed' -in $jobs.State) {
                    $jobs | Stop-Job 
                    $abort = $true
                    break
                }
                else {
                    $running | Wait-Job -Any | Out-Null
                    Write-Verbose "Waiting on jobs" -Verbose
                }
            }
            if ($abort) {
                exit 1
            }
        }
    }
    end {
        foreach ($j in $jobs) {
            if ($j.State -eq 'Failed') {
                $j.ChildJobs | ForEach-Object {
                    Write-Host ($_.JobStateInfo.Reason.Message) -ForegroundColor Red
                }
            }
            else {

                Write-Host "$($j.Name) $($j.State) successfully"
            }
        }       
    }
}