简体   繁体   中英

powershell start process within for each loop

I have a for each loop I wish to run in parallel, however I'm not getting a uniform time as to when each iteration kicks off, which is leading to some edgecase timing issues.

As such, I've changed my loop just to be sequential. However, I don't want to wait for the iteration commands to complete.

Each iteration is essentially doing:

Invoke-Pester @{Path= "tests.ps1"; Parameters = @{...}} -Tag 'value' -OutputFile $xmlpath -OutputFormat NUnitXML -EnableExit

I want each iteration to run sequentially (tests expect to be run sequentially) however I don't wish to wait for tests to complete.

What is the best way to ensure the iteration does not wait for the Invoke-Pester command to complete, such that the next iteration kicks off after the previous iteration has initiated? I've tried using Start-Process Invoke-Pester which I think invalidated further code structure.

Thank you

One way for async processing are PowerShell jobs . A very basic example:

$jobs = foreach ($xmlPath in (...)) {
    Start-job { Invoke-Pester -OutputFile $Args[0] ... } -ArgumentList $xmlPath
}

# get the job results later:
$jobs | Receive-Job

However, jobs are very slow. A more performant but also a little more complex way is using background runspaces :

$jobs = foreach ($xmlPath in (...)) {
    $ps = [Powershell]::Create()
    [void]$ps.AddScript({ Invoke-Pester -OutputFile $Args[0] ... })
    [void]$ps.AddArgument($xmlPath)
    @{
        PowerShell = $ps
        AsyncResult = $ps.BeginInvoke()
    }
}

# get results:
foreach ($job in $jobs) {
    $job.PowerShell.EndInvoke($_.AsyncResult)
    $job.PowerShell.Dispose()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM