In the previous tip we implemented a timeout using PowerShell background jobs so you could set a maximum time some code was allowed to run before it raised an exception.
Here is a more lightweight alternative that uses in-process threads rather than out-of-process executables:
function Invoke-CodeWithTimeout { param ( [Parameter(Mandatory)] [ScriptBlock] $Code, [int] $Timeout = 5 ) $ps = [PowerShell]::Create() $null = $ps.AddScript($Code) $handle = $ps.BeginInvoke() $start = Get-Date do { $timeConsumed = (Get-Date) - $start if ($timeConsumed.TotalSeconds -ge $Timeout) { $ps.Stop() $ps.Dispose() throw "Job timed out." } Start-Sleep -Milliseconds 300 } until ($handle.isCompleted) $ps.EndInvoke($handle) $ps.Runspace.Close() $ps.Dispose() }
And here is how to use the new timeout:
PS> Invoke-CodeWithTimeout -Code { Start-Sleep -Seconds 6; Get-Date } -Timeout 5
Job timed out.
At line:24 char:13
+ throw "Job timed out."
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Job timed out.:String) [], RuntimeException
+ FullyQualifiedErrorId : Job timed out.
PS> Invoke-CodeWithTimeout -Code { Start-Sleep -Seconds 3; Get-Date } -Timeout 5
Thursday November 1, 2018 14:53:26