Foreach-Object -Parallel is great. But sometimes the script block will hang, which will block the rest of the code. There is a timeOutSeconds parameter on the Foreach-Object, but it's a global one. When the timeout is reached, any remaining object in the queue is dropped. In my opinion, it's useless, the timeout should apply on each individual thread.
So I tried to write something short and efficient to get that behavior:
# Generate data
$list = 1..100
# Max Processing time for 1 item = 1s
$job_timeout = 1
# Processing data
$list |
ForEach-Object -parallel {
# using start-job to be able to cancel it if it takes too long
$j = Start-Job -InputObject $_ -ScriptBlock {
# Simulate processing time
Start-Sleep -Milliseconds (Get-Random -Min 0 -max 3000)
# returning processed data
$input
}
# building result object
[pscustomobject]@{
item = $_
# obtaining job result ($null if it's still running)
result = $j | Wait-Job -Timeout $using:job_timeout | Receive-job
}
# clean-up
$j | stop-job -PassThru | remove-job
}
My problem is that embedding a start-job inside a foreach-object -parallel seems dumb on a second thought. I could probably get the same result using only jobs without writing more lines.
So the question is, is there a good solution to have a per thread timeout in a foreach-object -parallel block.
Thanks for your help
Perhaps
ForEach-Object -Parallelis not the right cmdlet to approach this problem, it might be simpler to useStart-ThreadJobin this case.You could, in theory, implement a similar logic if using
-AsJobfromForEach-Object -Parallelthen targeting the.ChildJobsproperty but I would personally not try to force that, it would only make things more complicated than they should be.