При написании консольного приложения не так много обработчиков событий, связанных с окном консоли, но я обнаружил, что можно использовать System.Console.CancelKeyPress для прерывания текущего процесса с помощью события.
Предполагая следующую программу:
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.CancelKeyPress += myHandler;
while (true)
{
Console.WriteLine("Hello World!");
System.Threading.Thread.Sleep(1);
}
}
protected static void myHandler(object sender, ConsoleCancelEventArgs args)
{
args.Cancel = true;
Console.WriteLine(" Cancel property: {0}", args.Cancel);
Console.WriteLine("The read operation will resume...\n");
Console.ReadLine();
}
}
Программа печатает "Hello World!" бесконечно на экране. И прерывание работает, я предполагаю, что они разделяют поток, и на долю секунды он переходит в метод Handler, когда вы нажимаете Ctrl + C. Пока он выводит на экран информацию о текущем состоянии свойства cancel, Console.ReadLine () в событии полностью опускается.
Предназначено ли это поведение, чтобы избежать конфликтов блокировки, или есть трюк, как можно прочитать ввод, когда это событие запускается? Например, введите Y, если вы действительно хотите выйти.





Вы можете делать то, что хотите, следующим образом ...
class Program
{
private static bool running = true;
private static bool stop = false;
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.CancelKeyPress += myHandler;
while (!stop)
{
if (running)
{
Console.WriteLine("Hello World!");
}
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Exiting ...");
}
protected static void myHandler(object sender, ConsoleCancelEventArgs args)
{
args.Cancel = true;
running = false;
Console.WriteLine("Do you wish to resume... Y/N \n");
var resume = Console.ReadLine();
if (resume == "Y")
{
running = true;
}
else
{
stop = true;
}
}
}
Я подозреваю, что обработчик событий работает в другом контексте, чем основной поток окна консоли. Раньше я действительно не использовал события в окнах консоли, но в WinForms графический интерфейс будет работать в собственном потоке контекста.
Обработчик события отмены действительно работает в другом потоке (проверьте это, распечатав идентификатор потока).
Основной поток и вторичный поток, выполняющий событие, не «совместно используют поток», но используют вывод консоли как общий ресурс.
Строка чтения в событии не пропускается. Хотя «основной» поток действительно продолжает писать «Hello World», если вы нажмете клавишу ввода, обработчик событий эффективно прочитает введенные вами данные.
Если вы хотите, чтобы основной поток «приостанавливал» запись в консоль, вам нужно найти механизм для этого.
Вот очень наивная реализация:
private static bool paused;
static void Main(string[] args)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Console.ForegroundColor = ConsoleColor.Blue;
Console.CancelKeyPress += myHandler;
while (true)
{
if (!paused)
Console.WriteLine("Hello World!");
System.Threading.Thread.Sleep(1000);
}
}
protected static void myHandler(object sender, ConsoleCancelEventArgs args)
{
paused = true;
Console.WriteLine("Do you want to exit?");
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
var answer = Console.ReadLine();
args.Cancel = answer != "y";
paused = false;
}
Спасибо за объяснение, которое действительно прояснило, почему это так.