Powershell AcceptTcpClient () не может быть прерван Ctrl- C - PullRequest
2 голосов
/ 28 марта 2020

Я пишу простой TCP / IP-сервер, используя Powershell. Я заметил, что Ctrl- C не может прервать вызов AcceptTcpClient (). Ctrl- C работает нормально после звонка, хотя. Я искал вокруг, никто не сообщил о подобной проблеме до сих пор.

Проблема может быть повторена с помощью следующего простого кода. Я использую Windows 10, последний патч, с собственным терминалом Powershell, а не Powershell ISE.

$listener=new-object System.Net.Sockets.TcpListener([system.net.ipaddress]::any, 4444)
$listener.start()
write-host "listener started at port 4444"
$tcpConnection = $listener.AcceptTcpClient()
write-host "accepted a client"

Вот что происходит, когда я запускаю его

ps1> .\test_ctrl_c.ps1
listener started at port 4444
(Ctrl-C doesn't work here)

Ответы [ 2 ]

2 голосов
/ 28 марта 2020

Получив ответ @ mklement0, я отказался от своего исходного чистого кода. Я нашел обходной путь. Теперь Ctrl- C может прервать мою программу

$listener=new-object System.Net.Sockets.TcpListener([system.net.ipaddress]::any, 4444)
$listener.start()
write-host "listener started at port 4444"
while ($true) {
   if ($listener.Pending()) {
      $tcpConnection = $listener.AcceptTcpClient()
      break;
   }
   start-sleep -Milliseconds 1000
}
write-host "accepted a client"

Теперь Ctrl- C работает

ps1> .\test_ctrl_c.ps1
listener started at port 4444
(Ctrl-C works here)
1 голос
/ 28 марта 2020

(по состоянию на PowerShell 7.0) Ctrl- C работает только при выполнении кода PowerShell , а не во время выполнения метода . NET .

Поскольку большинство. NET вызовов методов выполняются быстро, проблема обычно не возникает.

См. эту проблему GitHub для обсуждение и справочная информация.


Что касается возможных обходных путей :

  • Наилучший подход - , если возможно - тот, который показан в ваш собственный ответ :

    • Запуск в al oop, который периодически опрашивает условие, спит между попытками и вызывает метод только тогда, когда условие выполняется Выполнение означает, что метод будет выполняться быстро, а не блокироваться бесконечно.
  • Если это не вариант (если нет такого условия, которое вы можете проверить), вы можете запустить метод блокировки в фоновом задании , чтобы он выполнялся в ch ild процесс , который может быть прерван по требованию вызывающей стороны; обратите внимание на ограничения этого подхода, однако:

    • Фоновые задания медленные и ресурсоемкие из-за необходимости запуска нового экземпляра PowerShell в скрытом дочернем элементе process.

    • Поскольку необходимо межпроцессное маршалинг входов и выходов из задания:

      • Входы и выходы не будут live объекты.
      • Сложные объекты (объекты, отличные от экземпляров примитива. NET типов и нескольких известных типов) будут эмуляциями исходных объектов; в сущности, объекты со stati c копиями значений свойств и без методов - см. этот ответ для справочной информации.

Вот простая демонстрация:

# Start the long-running, blocking operation in a background job (child process).
$jb = Start-Job -ErrorAction Stop {
  # Simulate a long-running, blocking .NET method call.
  [Threading.Thread]::Sleep(5000)
  'Done.'
}

$completed = $false
try {

  Write-Host -ForegroundColor Yellow "Waiting for background job to finish. Press Ctrl-C to abort."

  # Note: The output collected won't be *live* objects, and with complex
  #       objects will be *emulations* of the original objects that have
  #       static copies of their property values and no methods.
  $output = Receive-Job -Wait -Job $jb

  $completed = $true

}
finally { # This block is called even when Ctrl-C has been pressed.

  if (-not $completed) { Write-Warning 'Aborting due to Ctrl-C.' }

  # Remove the background job.
  #  * If it is still running and we got here due to Ctrl-C, -Force is needed
  #    to forcefully terminate it.
  #  * Otherwise, normal job cleanup is performed.
  Remove-Job -Force $jb

  # If we got here due to Ctrl-C, execution stops here.
}

# Getting here means: Ctrl-C was *not* pressed.

# Show the output received from the job.
Write-Host -ForegroundColor Yellow "Job output received:"
$output
  • Если вы выполните вышеуказанный скрипт и выполните не , нажмите Ctrl- C, вы увидите:

no Ctrl-C

  • Если вы do нажмете Ctrl- C, вы увидите:

Ctrl-C

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...