Что происходит, когда я прерываю консольное приложение С# с помощью Control-C?

Что происходит, когда я прерываю консольное приложение С# с помощью Control-C?

Неужели процесс убит? Освобождена ли память? Выполняются ли finally блоки? Что происходит с подключениями к базе данных?

Разве это отличается от приложения, созданного для отладки или выпуска, или запуска внутри/вне Visual Studio?

Ответы

Ответ 1

Короткий ответ: ничего не делать после CTRL-C

Длинный ответ: На MSDN есть хорошая статья, в которой четко говорится, что он посылает сигнал (прерывание) вместо нажатия клавиши.

Также существует событие cancelKeyPress, на которое вы можете подписаться и делать все, что захотите!

К сожалению, больше нет информации о том, что на самом деле сделано по умолчанию. Может быть, в худшем случае вы можете проверить это самостоятельно. Но, по-моему, должна быть какая-то документация по этому поводу...

ОБНОВЛЕНИЕ: Алоис Краус написал Codeproject-Article о изящном завершении консольного приложения после получения CTRL-C.

Цитирую Алоиса Крауса:

Поведение CLR по умолчанию - ничего не делать. Это означает, что CLR уведомляется очень поздно с помощью уведомления DLL_PROCESS_DETACH, в котором контекстный управляемый код больше не может выполняться, поскольку блокировка загрузчика ОС уже выполнена. Мы остаемся в печальной ситуации: мы не получаем никаких уведомлений и не запускаем финализаторы. Все потоки молча убиваются без возможности выполнить свои блоки catch/finally для упорядоченного завершения работы. Я сказал в первом предложении дефолт, потому что есть способ изящно справиться с этой ситуацией. Класс Console получил новый член события с .NET 2.0: Console.CancelKeyPress. Это позволяет вам получать уведомления о клавишах Ctrl-C и Ctrl-Break, где вы можете остановить выключение (только для Ctrl-C, но не Ctrl-Break). Основная проблема здесь в том, что если вы перехватываете событие Ctrl-C/Break и выходите из обработчика, финализаторы не вызываются. Это не то, что я бы назвал отключением из-за сотрудничества. Первое, что приходит мне в голову, это вызвать Environment.Exit, но он не вызывает финализаторы. Еще не все потеряно. Я придумал грязный трюк для запуска всех финализаторов: мы запустили небольшой вспомогательный поток внутри обработчика событий, который затем вызовет Environment.Exit. Вуаля, наши финализаторы называются.