如何在PowerShell中以响应方式检测Ctrl-C?

i34xakig  于 2023-10-18  发布在  Shell
关注(0)|答案(2)|浏览(164)

当我使用Ctrl-C中断PowerShell 7脚本时,我会让任何作业运行,保持运行。我也可能会让我一直在处理的文件处于不理想的状态。
我确实找到了一种检测按键的方法,但要么它消耗了太多CPU,要么React迟钝(或者两者兼而有之)。
看到

在使用下面的示例时,Ctrl-C的检测非常缓慢,或者将消耗大量CPU资源(或者两者兼而有之)。

[Console]::TreatControlCAsInput = $true
sleep 1
$Host.UI.RawUI.FlushInputBuffer()

Start-ThreadJob {# Do something
  sleep 5
} -Name 'SomeJob'

Start-ThreadJob {# Do another thing
  sleep 5
} -Name 'OtherJob'

while (Get-Job | where State -ne 'Stopped') {# Run the main loop

  if (# Some key was pressed
    $Host.UI.RawUI.KeyAvailable -and
    ($Key = $Host.UI.RawUI.ReadKey("AllowCtrlC,NoEcho,IncludeKeyUp"))
  ) {
    if ([int]$Key.Character -eq 3) {# Ctrl-C pressed
      Get-Job | Remove-Job -Force

      [Console]::TreatControlCAsInput = $false

      return

    }#end Ctrl-C pressed

  }#end Some key was pressed

  # sleep -Milliseconds 200
  $Host.UI.RawUI.FlushInputBuffer()
  
}

有没有好的方法来提高按键检测的响应速度?

yqkkidmi

yqkkidmi1#

你试图以错误的方式解决问题,finally块是专门为此设计的。请参阅使用finally释放资源
关于当前代码的高CPU和内存消耗,您已经有了答案,只是应该取消注解(sleep -Milliseconds 200)。

try {
    $jobs = @(
        Start-ThreadJob {
            Start-Sleep 10
        } -Name 'SomeJob'

        Start-ThreadJob {
            Start-Sleep 10
        } -Name 'OtherJob'
    )

    $jobs | Receive-Job -Wait -AutoRemoveJob
}
# this block will always run, even on CTRL+C
finally {
    $jobs | Remove-Job -Force
}

Get-Job # should be empty
3bygqnnd

3bygqnnd2#

我的解决方案是只停止工作。

Get-Job | Remove-Job -Force # Clean-up jobs from previous runs
try {
    $jJobs = @(
        Start-ThreadJob {
            Start-Sleep 10
        } -Name 'SomeJob'

        Start-ThreadJob {
            Start-Sleep 10
        } -Name 'OtherJob'
    )

    $Jobs | Receive-Job -Keep -Wait # Keep output for trouble shooting
}
# this block will always run, even on CTRL+C
finally {
    $Jobs | Stop-Job
}

Get-Job # should not contain any running jobs

相关问题