开始睡眠后(或直到脚本结束)对象输出的奇怪延迟
weird delay of the output of an object when followed by start-sleep (or until script end)
出于某种原因,对象在睡眠命令完成之前不会输出。
[pscustomobject]@{message = 'hi'}; sleep 5
这是另一个例子。在循环完成之前,您不会看到输出。
foreach ($i in 1..60) {
if ($i -eq 1) { [pscustomobject]@{message = $i} }
sleep 1
}
我猜你必须至少输出 2 个对象才能看到任何东西? ¯\_(ツ)_/¯ 15 秒后,您会看到两个对象。
foreach ($i in 1..60) {
if ($i -eq 1 -or $i -eq 15) { [pscustomobject]@{message = $i} }
sleep 1
}
或者输出足够的属性(> 4)来隐式调用 format-list 而不是 format-table。 格式-table是问题。马上就出来了。
[pscustomobject]@{a=1; b=2; c=3; d=4; e=5}; sleep 10
我想知道是否可以像 -NoWait
.
那样添加一个参数到 format-table
格式文件包含列宽的已知对象类型不存在此问题。
foreach ($i in 1..60) {
if ($i -eq 1) { get-process powershell }
sleep 1
}
或默认为自定义格式的对象:
foreach ($i in 1..60) {
if ($i -eq 1) { get-date }
sleep 1
}
将您的自定义对象通过管道传输到 Out-Host
cmdlet:
[pscustomobject]@{message = 'hi'} | Out-Host; sleep 5
当您使用 Out-Host
cmdlet 时,您会立即向主机显示结果。没有它,对象将输出到管道,直到 Start-Sleep
cmdlet 之后才会返回。
tl;dr
如果命令的输出结果是自动表格显示(隐式 Format-Table
),显示 输出可以情境 最多延迟 300 毫秒。 (请参阅下文了解原因和时间),这可能会产生两个意想不到的效果:
如问题所示,在延迟结束之前提交的后续 Start-Sleep
进一步延迟输出(至少)持续时间睡眠 - 它有效地 暂停 完成 300 毫秒。等等。
A 后续 Write-Host
或 Out-Host
调用可能会产生意外出现的输出 first.
您可以 force 同步 display 通过管道将命令输出到 Out-Host
或 Format-Table
显式(或任何其他 Format-*
cmdlet)。
- 但是,这样做意味着只生成 for-display 输出,这意味着您失去了(有意义地)捕获或中继命令输出的能力。
# The Out-Host forces instant display, before sleeping starts.
# However, use of Out-Host means you can't capture the output.
[pscustomobject] @{message = 'hi'} | Out-Host; sleep 5
该行为由臭名昭著的 解释:对于 没有预定义格式数据 且具有 4 个或更少属性的数据类型 (这是 auto-selects table 显示的内容),它最多等待 300 毫秒。在显示输出之前,努力确定 suitable 列宽。
如果您在该时间段结束前使用 Start-Sleep
,您会 暂停 等待,直到您在睡觉。
未触发隐式Format-Table
格式化的输出对象不受影响,但是:
# Immediate output, before sleeping ends:
# Out-of-band formatting of a .NET primitive.
PS> 1; Start-Sleep 5
# Implicit Format-*List* formatting due to having 5+ properties.
PS> [pscustomobject]@{a=1; b=2; c=3; d=4; e=5}; sleep 10
相比之下,因为您的命令输出是一个只有 1 属性 的对象,并且它的类型 ([pscustomobject]
) 没有与它,它会触发隐式 Format-Table
格式化,因此会出现问题。
简而言之:以下命令输出受到影响,因为它们select隐式Format-Table
输出同时缺少预定义的列宽,需要延迟:
类型恰好具有 4 个或更少 属性的对象
if 这些类型有 no 关联的预定义格式数据 (参见 about_Format.ps1xml
),这通常适用于 [pscustomobject]
个实例。
- 另外,但不太常见的是,使用默认为table视图但没有的格式数据键入列 宽度 预定义,也会受到影响(例如,
New-Guid
输出的 System.Guid
类型实例)。
类型没有具有5个或更多属性的格式化数据默认隐式应用Format-List
,其中,由于行逐行输出,不需要确定有用的列宽,因此没有延迟。
请注意,这只是一个 显示 问题,如果命令被捕获或发送到管道,数据 是 立即输出(尽管在 Start-Sleep
时间段过去之前命令不会整体完成):
# The ForEach-Object command's script block receives the [pscustomobject]
# instance right away (and itself prints it *immediately* to the display,
# due to outputting a *string* (which never triggers the asynchronous behavior).
& { [pscustomobject]@{message = 'hi'}; sleep 5 } | ForEach-Object { "[$_]" }
虽然有几种方法可以强制同步(立即)显示输出,它们都会改变命令的基本行为:
# Piping to Out-Host:
# Directly prints to the *display* (host).
# No way for a caller to capture the result or for processing
# the result in a pipeline.
[pscustomobject]@{message = 'hi'} | Out-Host; sleep 5
# Using Write-Host:
# Prints directly to the *display* (host) by default.
# While it *is* possible to capture the result via output stream 6.
# the information stream (6> file.txt), that output:
# * is invariably converted to *strings*
# * and the string representation does *not* use the friendly default
# output formatting; instead, the objects are stringified with simple
# [psobject.].ToString() calls, which results in a much less friendly
# representation.
Write-Host ([pscustomobject]@{message = 'hi'}); sleep 5
# Piping to a Format-* cmdlet explicitly:
# While this does write to the success-output stream (stream number 1),
# as the command would by default, what is written isn't the original
# objects, but *formatting instructions*, which are useless for further
# programmatic processing.
# However, for redirecting the output to a file with Out-File or >
# this makes no difference, because they convert the formatting instructions
# to the strings you would see on the screen by default.
# By contrast, using Set-Content or any other cmdlet that expects actual data
# would not work meaningfully.
[pscustomobject]@{message = 'hi'} | Format-Table; sleep 5
输出少于5个属性,format-table隐式运行。在显示第一个对象之前,格式-table 将为第二个对象等待 不确定的 时间量。这适用于没有定义 default table 视图的 xml 文件的对象类型(如 pscustomobject)。
# no output for 5 seconds
&{get-date
sleep 5
get-date} | format-table
DisplayHint DateTime Date Day DayOfWeek DayOfYear Hour Kind Millisecond Minute
----------- -------- ---- --- --------- --------- ---- ---- ----------- ------
DateTime Saturday, February 8, 2020 10:24:48 AM 2/8/2020 12:00:00 AM 8 Saturday 39 10 Local 618 24
DateTime Saturday, February 8, 2020 10:24:53 AM 2/8/2020 12:00:00 AM 8 Saturday 39 10 Local 892 24
与格式列表比较:
& {get-date
sleep 5
get-date} | format-list
DisplayHint : DateTime
Date : 2/8/2020 12:00:00 AM
Day : 8
DayOfWeek : Saturday
DayOfYear : 39
Hour : 20
Kind : Local
Millisecond : 408
Minute : 37
Month : 2
Second : 18
Ticks : 637167910384087860
TimeOfDay : 20:37:18.4087860
Year : 2020
DateTime : Saturday, February 8, 2020 8:37:18 PM
DisplayHint : DateTime
Date : 2/8/2020 12:00:00 AM
Day : 8
DayOfWeek : Saturday
DayOfYear : 39
Hour : 20
Kind : Local
Millisecond : 662
Minute : 37
Month : 2
Second : 23
Ticks : 637167910436622480
TimeOfDay : 20:37:23.6622480
Year : 2020
DateTime : Saturday, February 8, 2020 8:37:23 PM
出于某种原因,对象在睡眠命令完成之前不会输出。
[pscustomobject]@{message = 'hi'}; sleep 5
这是另一个例子。在循环完成之前,您不会看到输出。
foreach ($i in 1..60) {
if ($i -eq 1) { [pscustomobject]@{message = $i} }
sleep 1
}
我猜你必须至少输出 2 个对象才能看到任何东西? ¯\_(ツ)_/¯ 15 秒后,您会看到两个对象。
foreach ($i in 1..60) {
if ($i -eq 1 -or $i -eq 15) { [pscustomobject]@{message = $i} }
sleep 1
}
或者输出足够的属性(> 4)来隐式调用 format-list 而不是 format-table。 格式-table是问题。马上就出来了。
[pscustomobject]@{a=1; b=2; c=3; d=4; e=5}; sleep 10
我想知道是否可以像 -NoWait
.
格式文件包含列宽的已知对象类型不存在此问题。
foreach ($i in 1..60) {
if ($i -eq 1) { get-process powershell }
sleep 1
}
或默认为自定义格式的对象:
foreach ($i in 1..60) {
if ($i -eq 1) { get-date }
sleep 1
}
将您的自定义对象通过管道传输到 Out-Host
cmdlet:
[pscustomobject]@{message = 'hi'} | Out-Host; sleep 5
当您使用 Out-Host
cmdlet 时,您会立即向主机显示结果。没有它,对象将输出到管道,直到 Start-Sleep
cmdlet 之后才会返回。
tl;dr
如果命令的输出结果是自动表格显示(隐式
Format-Table
),显示 输出可以情境 最多延迟 300 毫秒。 (请参阅下文了解原因和时间),这可能会产生两个意想不到的效果:如问题所示,在延迟结束之前提交的后续
Start-Sleep
进一步延迟输出(至少)持续时间睡眠 - 它有效地 暂停 完成 300 毫秒。等等。A 后续
Write-Host
或Out-Host
调用可能会产生意外出现的输出 first.
您可以 force 同步 display 通过管道将命令输出到
Out-Host
或Format-Table
显式(或任何其他Format-*
cmdlet)。- 但是,这样做意味着只生成 for-display 输出,这意味着您失去了(有意义地)捕获或中继命令输出的能力。
# The Out-Host forces instant display, before sleeping starts.
# However, use of Out-Host means you can't capture the output.
[pscustomobject] @{message = 'hi'} | Out-Host; sleep 5
该行为由臭名昭著的
如果您在该时间段结束前使用 Start-Sleep
,您会 暂停 等待,直到您在睡觉。
未触发隐式Format-Table
格式化的输出对象不受影响,但是:
# Immediate output, before sleeping ends:
# Out-of-band formatting of a .NET primitive.
PS> 1; Start-Sleep 5
# Implicit Format-*List* formatting due to having 5+ properties.
PS> [pscustomobject]@{a=1; b=2; c=3; d=4; e=5}; sleep 10
相比之下,因为您的命令输出是一个只有 1 属性 的对象,并且它的类型 ([pscustomobject]
) 没有与它,它会触发隐式 Format-Table
格式化,因此会出现问题。
简而言之:以下命令输出受到影响,因为它们select隐式Format-Table
输出同时缺少预定义的列宽,需要延迟:
类型恰好具有 4 个或更少 属性的对象
if 这些类型有 no 关联的预定义格式数据 (参见
about_Format.ps1xml
),这通常适用于[pscustomobject]
个实例。- 另外,但不太常见的是,使用默认为table视图但没有的格式数据键入列 宽度 预定义,也会受到影响(例如,
New-Guid
输出的System.Guid
类型实例)。
- 另外,但不太常见的是,使用默认为table视图但没有的格式数据键入列 宽度 预定义,也会受到影响(例如,
类型没有具有5个或更多属性的格式化数据默认隐式应用Format-List
,其中,由于行逐行输出,不需要确定有用的列宽,因此没有延迟。
请注意,这只是一个 显示 问题,如果命令被捕获或发送到管道,数据 是 立即输出(尽管在 Start-Sleep
时间段过去之前命令不会整体完成):
# The ForEach-Object command's script block receives the [pscustomobject]
# instance right away (and itself prints it *immediately* to the display,
# due to outputting a *string* (which never triggers the asynchronous behavior).
& { [pscustomobject]@{message = 'hi'}; sleep 5 } | ForEach-Object { "[$_]" }
虽然有几种方法可以强制同步(立即)显示输出,它们都会改变命令的基本行为:
# Piping to Out-Host:
# Directly prints to the *display* (host).
# No way for a caller to capture the result or for processing
# the result in a pipeline.
[pscustomobject]@{message = 'hi'} | Out-Host; sleep 5
# Using Write-Host:
# Prints directly to the *display* (host) by default.
# While it *is* possible to capture the result via output stream 6.
# the information stream (6> file.txt), that output:
# * is invariably converted to *strings*
# * and the string representation does *not* use the friendly default
# output formatting; instead, the objects are stringified with simple
# [psobject.].ToString() calls, which results in a much less friendly
# representation.
Write-Host ([pscustomobject]@{message = 'hi'}); sleep 5
# Piping to a Format-* cmdlet explicitly:
# While this does write to the success-output stream (stream number 1),
# as the command would by default, what is written isn't the original
# objects, but *formatting instructions*, which are useless for further
# programmatic processing.
# However, for redirecting the output to a file with Out-File or >
# this makes no difference, because they convert the formatting instructions
# to the strings you would see on the screen by default.
# By contrast, using Set-Content or any other cmdlet that expects actual data
# would not work meaningfully.
[pscustomobject]@{message = 'hi'} | Format-Table; sleep 5
输出少于5个属性,format-table隐式运行。在显示第一个对象之前,格式-table 将为第二个对象等待 不确定的 时间量。这适用于没有定义 default table 视图的 xml 文件的对象类型(如 pscustomobject)。
# no output for 5 seconds
&{get-date
sleep 5
get-date} | format-table
DisplayHint DateTime Date Day DayOfWeek DayOfYear Hour Kind Millisecond Minute
----------- -------- ---- --- --------- --------- ---- ---- ----------- ------
DateTime Saturday, February 8, 2020 10:24:48 AM 2/8/2020 12:00:00 AM 8 Saturday 39 10 Local 618 24
DateTime Saturday, February 8, 2020 10:24:53 AM 2/8/2020 12:00:00 AM 8 Saturday 39 10 Local 892 24
与格式列表比较:
& {get-date
sleep 5
get-date} | format-list
DisplayHint : DateTime
Date : 2/8/2020 12:00:00 AM
Day : 8
DayOfWeek : Saturday
DayOfYear : 39
Hour : 20
Kind : Local
Millisecond : 408
Minute : 37
Month : 2
Second : 18
Ticks : 637167910384087860
TimeOfDay : 20:37:18.4087860
Year : 2020
DateTime : Saturday, February 8, 2020 8:37:18 PM
DisplayHint : DateTime
Date : 2/8/2020 12:00:00 AM
Day : 8
DayOfWeek : Saturday
DayOfYear : 39
Hour : 20
Kind : Local
Millisecond : 662
Minute : 37
Month : 2
Second : 23
Ticks : 637167910436622480
TimeOfDay : 20:37:23.6622480
Year : 2020
DateTime : Saturday, February 8, 2020 8:37:23 PM