Powershell 在开始睡眠(或直到脚本结束)之后,对象输出的奇怪延迟

Powershell 在开始睡眠(或直到脚本结束)之后,对象输出的奇怪延迟,powershell,object,output,sleep,Powershell,Object,Output,Sleep,由于某些原因,在执行sleep命令之前,对象不会输出 [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..

由于某些原因,在执行sleep命令之前,对象不会输出

[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。format 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主机
cmdlet:

[pscustomobject]@{message = 'hi'} | Out-Host; sleep 5
使用
Out-Host
cmdlet时,将立即向主机显示结果。如果没有它,对象将输出到管道,直到
Start-Sleep
cmdlet之后才会返回该管道。

tl;dr

  • 如果命令的输出导致自动表格显示(隐式
    格式表格
    ),则显示输出可能会在特定情况下延迟300毫秒(原因和时间见下文),这可能会产生两种意想不到的效果:

    • 如问题中所述,在延迟结束之前提交的后续
      启动睡眠
      会进一步延迟(至少)睡眠持续时间的输出-它实际上会暂停完成300毫秒的等待

    • 后续的
      写入主机
      输出主机
      调用可能会产生意外先到的输出

  • 您可以通过管道将命令显式地发送到
    Out Host
    Format Table
    (或任何其他
    Format-*
    cmdlet),强制同步显示输出

    • 但是,这样做意味着仅为显示输出生成,这意味着您将失去(有意义地)捕获或中继命令输出的能力

这种行为被臭名昭著的解释为:对于没有预定义格式的数据类型,如果数据具有4个或更少的属性(这是自动选择表显示的内容),它最多会等待300毫秒。在显示输出之前,它会努力确定合适的列宽

如果在这段时间过去之前使用了
Start Sleep
,则在睡眠期间暂停等待

不触发隐式
格式表
格式的输出对象不受影响,但是:

# 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]
)没有与之关联的预定义格式数据,因此它会触发隐式
格式表
格式,因此会出现问题

简而言之:以下命令输出受到影响,因为它们选择隐式
格式表
输出,但缺少预定义的列宽,因此需要延迟:

  • 类型恰好具有4个或更少属性的对象

  • 如果这些类型没有关联的预定义格式数据(请参阅),则对于
    [pscustomobject]
    实例通常是这样

    • 此外,具有默认为表视图但没有预定义列宽的格式数据的类型(例如,
      newguid
      输出的类型实例)也会受到影响,但不太常见
没有格式化数据且具有5个或更多属性的类型默认为隐式应用的
格式列表
,其中,由于逐行输出,不需要确定有用的列宽,因此没有延迟


请注意,这只是一个显示问题,如果捕获该命令或将其发送到管道,则会立即输出数据(尽管在
开始睡眠
期间结束之前,该命令不会全部完成):


虽然有几种方法可以强制同步(立即)显示输出,但它们都会改变命令的基本行为:


输出少于5个属性,format table将隐式运行。format 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

这回答了你的问题吗?@bacon我可以睡觉,我只是看不到及时的输出。@js2010这个问题的要点并不是说
暂停
/
睡眠
根本没有发生,而是它们发生在一个命令之前,该命令尽管在之后被调用,但仍然会产生输出,这似乎与你描述的问题相同我在这里重复。可能有更好的重复建议,但这个问题似乎是一个有许多重复链接的问题。再次,我不确定我是否知道什么构成这个网站上的潜在重复(如果它是基于一个共同的问题或相互适用的答案)…@BACON,另一个近乎重复的是,它链接到了你提到的帖子。问题是,有时根本原因可能是相同的,但触发场景和症状完全不同,并且与根本原因没有明显的联系,因此没有必要进行具体的解释。我个人的M.O.是:在回答,但链接到解释根本原因的近似重复项。对象被输出到管道,直到
Start Sleep
cmdlet之后才会返回该对象。OP的问题是知道何时应用该命令。另外值得一提的是,使用
Out Host
意味着命令输出将打印直接放在显示器(主机)上,再也无法捕获/重定向。太棒了
# 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
# 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