Создание консольного приложения, которое записывает строку вывода и завершает работу при нажатии Ctrl+C.C#

Место общения программистов C#
Ответить
Anonymous
 Создание консольного приложения, которое записывает строку вывода и завершает работу при нажатии Ctrl+C.

Сообщение Anonymous »

Я хочу создать консольное приложение, которое выводит «сводный оператор» в качестве последней строки вывода, когда оно завершается с помощью Ctrl+C, но у меня возникли проблемы с тем, чтобы это работало. Частично это может быть связано с тем, что приложение, которое я пытаюсь создать, постоянно записывает выходные данные в цикле while(true). Лучше всего я могу проиллюстрировать проблему на простом примере:
Предположим, у меня есть консольное приложение, которое постоянно выводит текущее время:

Код: Выделить всё

while (true)
{
var now = DateTime.Now;
Console.Write(now);
Console.Write(" ");
Console.Write(now.Millisecond);
Console.CursorLeft = 0; // Overwrite the same line
}
Это работает, и я могу закрыть приложение с помощью Ctrl+C:

Код: Выделить всё

23/02/2023 23:07:14 658
Теперь, когда я нажимаю Ctrl+C, я хочу, чтобы текст Goodbye! отображался в последней строке вывода:

Код: Выделить всё

23/02/2023 23:09:56 441
Goodbye!
Однако у меня возникли проблемы с тем, чтобы это работало. Вот моя первая попытка:

Код: Выделить всё

Console.CancelKeyPress += OnCancel;

while (true)
{
var now = DateTime.Now;
Console.Write(now);
Console.Write(" ");
Console.Write(now.Millisecond);
Console.CursorLeft = 0; // Overwrite the same line
}

void OnCancel(object? sender, ConsoleCancelEventArgs e)
{
Console.WriteLine("Goodbye");
}
Однако это приводит к «искаженному» выводу, например:

Код: Выделить всё

Goodbye023 23:14:55 670
23/02/2023 23:14:55
Я думаю, это происходит потому, что обработчик событий Console.CancelKeyPress выполняется в отдельном рабочем потоке, а вызов Console.WriteLine("Goodbye"); может произойти в любой точке цикла while. В идеале обработчик событий CancelKeyPress не запускается до тех пор, пока не завершится текущая итерация цикла while. Я не уверен, как это сделать потокобезопасным способом.
Я пробовал разные подходы и не буду перечислять код для них, но вкратце все перечисленное ниже я пробовал безрезультатно:
  • Определил логическую переменную cancelRequested в верхней области видимости и установил условие цикла while
    !cancelRequested; В OnCancel установите для переменной значение true;

    Код: Выделить всё

    Console.WriteLine("Goodbye!")
    после цикла. Это блокирует

    Код: Выделить всё

    Console.WriteLine("Goodbye!")
    (тупик?).
  • Аналогично приведенному выше, но используется CancellationTokenSource вместо логической переменной.
    Наблюдается такое же поведение взаимоблокировки, так что я думаю, это эквивалентно?


Подробнее здесь: https://stackoverflow.com/questions/755 ... upon-ctrlc
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»