创建一个控制台应用程序,以线程安全的方式写入输出行并在 Ctrl+C 时退出

问题描述 投票:0回答:0

我想创建一个控制台应用程序,在使用 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
循环的当前迭代完成之前不会运行。我不确定如何以线程安全的方式执行此操作。

我尝试了不同的方法,我不会列出它们的代码,但总而言之,我尝试了以下所有方法都无济于事:

  1. 在顶部范围定义了一个布尔变量
    cancelRequested
    并设置
    while
    循环条件为
    !cancelRequested
    ;在
    OnCancel
    中将var设置为
    true
    Console.WriteLine("Goodbye!")
    循环后。这阻止了
    Console.WriteLine("Goodbye!")
    线(死锁?)。
  2. 与上面类似,但使用
    CancellationTokenSource
    而不是布尔变量。 观察到相同的死锁行为,所以我猜这是等价的?
c# multithreading thread-safety console-application deadlock
© www.soinside.com 2019 - 2024. All rights reserved.