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.KeyAvailablelub blokowania Console.ReadKey. Chociaż prawdą jest, że .NET Consolenie jest tu zbyt kooperatywny, możesz Task.Runprzejść do bardziej nowoczesnego Asynctrybu słuchania.
Głównym problemem, o którym należy pamiętać, jest to, że domyślnie wątek konsoli nie jest skonfigurowany do Asyncdziałania - co oznacza, że gdy wypadniesz z dołu mainfunkcji, zamiast Asyncczekać 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 Asyncwsparcia 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
}
}