我想知道保持 PowerShell 脚本运行而不使主线程进入睡眠状态的最佳方法。使用Start-Sleep保持脚本活动状态会产生阻塞同一线程上运行的异步事件处理程序的副作用。
考虑以下脚本,它演示了这种阻塞的实际情况。
$Timer = [System.Timers.Timer]::new(500)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action { Write-Host -ForegroundColor Blue hi }
$Timer.Start()
Start-Sleep -Seconds 5
Run Code Online (Sandbox Code Playgroud)
运行此脚本时,您将看到在命令完成Timer之前,它的处理程序被阻止执行。Start-Sleep但是,您还会注意到事件在后台排队,并且一旦主线程被释放,所有事件都会快速连续触发。
Start-Sleep此外,一旦命令运行完毕,脚本就会退出。
问题:如何保持 PowerShell 进程/脚本运行而不阻塞事件处理程序?
小智 4
大约一年前,我在 GitHub 上的 PowerShell Polaris 存储库上提出了类似的问题。该特定模块的答案是使用 PowerShellWait-Event命令。
使用Wait-Event随机命令-SourceIdentifier将阻止主线程的进一步执行,而不会阻止事件处理程序的执行。
$Timer = [System.Timers.Timer]::new(500)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action { Write-Host -ForegroundColor Blue hi }
$Timer.Start()
Wait-Event -SourceIdentifier SomeEventIdThatWillNeverExist
Run Code Online (Sandbox Code Playgroud)
如果脚本已“完成”(无论这对作者意味着什么),并且注册的事件处理程序希望终止脚本,他们可以这样做。
-Action在本例中,定时器上的事件处理程序可以选择使用内置命令来触发一个事件,并将SomeEventIdThatWillNeverExist用作其参数值。否则,外部人员可以在适当的时候强制终止该进程。-SourceIdentifierNew-Event
$Timer = [System.Timers.Timer]::new(500)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action {
Write-Host -ForegroundColor Blue hi
if ((Get-Random -Maximum 100) -gt 95) {
New-Event -SourceIdentifier SomeEventIdThatWillNeverExist
}
}
$Timer.Start()
Wait-Event -SourceIdentifier SomeEventIdThatWillNeverExist
Run Code Online (Sandbox Code Playgroud)
在交互式 PowerShell 会话中,计时器将在脚本完成执行后继续运行。您需要使用单独的 PowerShell 进程(即pwsh -File timer.ps1)来调用脚本。
目前,这是我所知道的最好答案。然而,如果有更好的方法来实现这一点,我愿意接受新的答案。
| 归档时间: |
|
| 查看次数: |
1536 次 |
| 最近记录: |