For some reason, the object won't output until the sleep command is done.
[pscustomobject]@{message = 'hi'}; sleep 5
Here's another example. You won't see the output until the loop finishes.
foreach ($i in 1..60) {
if ($i -eq 1) { [pscustomobject]@{message = $i} }
sleep 1
}
I guess you have to output at least 2 objects to see anything? ¯\_(ツ)_/¯ After 15 seconds, you see both objects.
foreach ($i in 1..60) {
if ($i -eq 1 -or $i -eq 15) { [pscustomobject]@{message = $i} }
sleep 1
}
Or output enough properties (> 4) to implicitly call format-list instead of format-table. Format-table is the problem. This comes out right away.
[pscustomobject]@{a=1; b=2; c=3; d=4; e=5}; sleep 10
I wonder if a parameter to format-table could be added like -NoWait
.
Known object types with format files containing column widths don't have this problem.
foreach ($i in 1..60) {
if ($i -eq 1) { get-process powershell }
sleep 1
}
Or objects that default to format-custom:
foreach ($i in 1..60) {
if ($i -eq 1) { get-date }
sleep 1
}
Pipe your custom object to the
Out-Host
cmdlet:When you use the
Out-Host
cmdlet, you are immediately displaying the results to the host. Without it, the object is output to the pipeline which is not returned until after theStart-Sleep
cmdlet.Output less than 5 properties, and format-table implicitly runs. Format-table will wait an indefinite amount of time for the second object, before displaying the first object. This is for object types (like pscustomobject) without an xml file that define a default table view.
Compare with format-list:
tl;dr
If a command's output results in automatic tabular display (implicit
Format-Table
), display output can situationally be delayed for up to 300 ms. (see below for why and when), which can have two unexpected effects:As in the question, a subsequent
Start-Sleep
submitted before the delay has elapsed further delays output for (at least) the duration of the sleep - it effectively suspends completing the 300 ms. wait.A subsequent
Write-Host
orOut-Host
call can produce output that unexpectedly comes first.You can force synchronous display output by piping the command to
Out-Host
or toFormat-Table
explicitly (or any of the otherFormat-*
cmdlets).The behavior is explained by the infamous PSv5+ asynchronous behavior of implicitly applied
Format-Table
output: For data types without predefined formatting data that have 4 or fewer properties (which is what auto-selects table display), it waits for up to 300 msecs. before displaying output, in an effort to determine suitable column widths.If you use
Start-Sleep
before that period has elapsed, you suspend waiting for as long as you're sleeping.Output objects that happen not to trigger implicit
Format-Table
formatting are not affected, however:By contrast, because your command's output is an object with just 1 property and its type (
[pscustomobject]
) has no predefined formatting data associated with it, it triggers implicitFormat-Table
formatting and therefore exhibits the problem.In short: The following command outputs are affected, because they select implicit
Format-Table
output while lacking predefined column widths, necessitating the delay:objects whose type happens to have 4 or fewer properties
if those types have no associated predefined formatting data (see
about_Format.ps1xml
), which is generally true for[pscustomobject]
instances.System.Guid
type instances thatNew-Guid
outputs).Types without formatting data that have 5 or more properties default to implicitly applied
Format-List
, where, due to line-by-line output, there's no need to determine useful column widths, and therefore no delay.Note that this is only a display problem, and that if the command is captured or sent to a pipeline the data is immediately output (though the command won't finish overall until the
Start-Sleep
period has elapsed):While there are several ways to force synchronous (immediate) display output, they all change the fundamental behavior of the command: