Rozwiązanie problemów, z którymi niektóre inne odpowiedzi nie radzą sobie dobrze:
- Responsive : bezpośrednie wykonanie kodu obsługi naciśnięcia klawisza; pozwala uniknąć kaprysów opóźnień związanych z odpytywaniem lub blokowaniem
- Opcjonalnie : globalne naciśnięcie klawisza jest opcjonalne ; w przeciwnym razie aplikacja powinna zakończyć się normalnie
- Rozdzielenie obaw : mniej inwazyjny kod nasłuchu; działa niezależnie od normalnego kodu aplikacji konsoli.
Wiele rozwiązań na tej stronie wymaga odpytywania Console.KeyAvailable
lub blokowania Console.ReadKey
. Chociaż prawdą jest, że .NET Console
nie jest tu zbyt kooperatywny, możesz Task.Run
przejść do bardziej nowoczesnego Async
trybu słuchania.
Głównym problemem, o którym należy pamiętać, jest to, że domyślnie wątek konsoli nie jest skonfigurowany do Async
działania - co oznacza, że gdy wypadniesz z dołu main
funkcji, zamiast Async
czekać na zakończenie, twoja aplikacja i proces zakończą się . Właściwym sposobem rozwiązania tego problemu byłoby użycie AsyncContext Stephena Cleary'ego do ustanowienia pełnego Async
wsparcia w jednowątkowym programie konsoli. Ale w prostszych przypadkach, takich jak oczekiwanie na naciśnięcie klawisza, zainstalowanie pełnej trampoliny może być przesadą.
Poniższy przykład dotyczy programu konsoli używanego w pewnego rodzaju iteracyjnym pliku wsadowym. W takim przypadku, gdy program zakończy pracę, zwykle powinien zakończyć działanie bez konieczności naciskania klawisza, a następnie zezwalamy na opcjonalne naciśnięcie klawisza, aby uniemożliwić zamknięcie aplikacji. Możemy wstrzymać cykl w celu zbadania rzeczy, być może wznowić, lub użyć pauzy jako znanego „punktu kontrolnego”, w którym można czysto wyrwać się z pliku wsadowego.
static void Main(String[] args)
{
Console.WriteLine("Press any key to prevent exit...");
var tHold = Task.Run(() => Console.ReadKey(true));
// ... do your console app activity ...
if (tHold.IsCompleted)
{
#if false // For the 'hold' state, you can simply halt forever...
Console.WriteLine("Holding.");
Thread.Sleep(Timeout.Infinite);
#else // ...or allow continuing to exit
while (Console.KeyAvailable)
Console.ReadKey(true); // flush/consume any extras
Console.WriteLine("Holding. Press 'Esc' to exit.");
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
;
#endif
}
}