首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Timers.Timer瘫痪脚本

Timers.Timer瘫痪脚本
EN

Stack Overflow用户
提问于 2021-09-25 14:59:37
回答 1查看 50关注 0票数 1

我正在尝试运行示例:

代码语言:javascript
复制
Clear-Host
$timer = [Timers.Timer]::new()
$timer.Interval = 200
$action = {
    if($complete -eq 8){
        write-host "completed $complete" -ForegroundColor Red
        write-host "Timer stopped" -ForegroundColor Red
        $timer.stop()
        Unregister-Event thetimer
    }
}
Register-ObjectEvent -InputObject $timer -EventName elapsed `
–SourceIdentifier  thetimer -Action $action

$complete = 0
$timer.Start()

while($true){
    Write-Host "Script working: $complete" -ForegroundColor Green
    Start-Sleep -m 400
    $complete++
}

但是当计时器停止时,脚本就瘫痪了。

我做错了什么,怎么解决?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-25 17:19:14

  • 除非您在全局范围内直接执行它(通过在提示符处粘贴它,或者通过点源包含它的脚本),否则您的代码根本无法正常工作。
代码语言:javascript
复制
- The reason is that **a script block passed to** [**`Register-ObjectEvent`**](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/register-objectevent)**'s** **`-Action`** **parameter runs inside a** _**dynamic module**_**, which sees only the** _**global**_ **scope's variables, not that of any other caller**, such as a script's.
  • 如果您确实从全局范围运行,则-Action 挂起是由在脚本块中调用 注销-事件 引起的。
代码语言:javascript
复制
- **Call it from the** _**caller's scope**_ **instead** (i.e. from the same scope where `Register-ObjectEvent` was called).
代码语言:javascript
复制
- That the code _hangs_ when called from inside the `-Action` script block (happens up to at least PowerShell 7.1, the version current as of this writing) should be considered a _bug_; it seems to occur when _more events are pending_ at the time `Unregister-Event` is called; the problem has been reported in [GitHub issue #16154](https://github.com/PowerShell/PowerShell/issues/16154)

下面是一个自包含的工作示例,您也可以从脚本中调用该示例:

代码语言:javascript
复制
$timer = [Timers.Timer]::new()
$timer.Interval = 200

$action = {
  # Note: This script block generally does NOT see the caller's variables.
  # Refer to the originating timer object with $Event.Sender or $args[0]
  $timer = $Event.Sender
  # Get the variable object passed to -MessageData, via $Event.MessageData
  $counter = $Event.MessageData.Value
  # Note: Since you're only *getting* an *integer* value, you needn't worry
  #       about thread synchronization.
  if ($timer.Enabled -and $counter -ge 8) { 
      write-host "completed $counter" -ForegroundColor Red
      write-host "Timer stopped" -ForegroundColor Red
      $timer.stop()
      # Do NOT try to call Unregister-Event here - it'll cause a hang.
  }
}

# Initialize the counter variable.
$complete = 0

# Get the variable as a variable *object* that can be passed to the -Action
# script block with -MessageData.
$counterVarObject = Get-Variable complete

# Register the event and pass the variable object with -MessageData.
$evtJob = Register-ObjectEvent -InputObject $timer -EventName elapsed `
                               –SourceIdentifier thetimer `
                               -Action $action -MessageData $counterVarObject

$timer.Start()

try {
  while ($timer.Enabled) { # Loop until the timer stops.
      Write-Host "Script working: $complete" -ForegroundColor Green
      Start-Sleep -MilliSeconds 400
      $complete++
  }
}
finally { # This is called even if the loop is aborted with Ctrl-C.
  # Remove the event job, which also unregisters the event.
  $evtJob | Remove-Job -Force
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69327313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档