如何检测控制台应用程序在鼠标单击时冻结

4
我有一个简单的WCF服务,我在测试时在控制台运行它。有时我希望控制台窗口置于其他窗口之上,所以我点击它。这会激活“标记和粘贴”命令,然后冻结整个应用程序(服务变得无响应),直到我按下回车键。
我觉得这相当烦人。
我不想禁用“标记和粘贴”,因为有时我需要从控制台复制文本。
是否有任何方法可以检测应用程序是否已冻结?
如果我知道这种情况发生的时间,我可以更改窗口标题以显示警告。
编辑: 这不是重复问题,因为我想知道如何处理冻结,而不是为什么感觉冻结。我现在知道只有输出写入被冻结,这导致我的应用程序感觉像是被冻结了。

2
一个 冻结的 应用程序无法检测任何内容。如果您想复制文本,您必须将其记录下来。 - Panagiotis Kanavos
如果像重复问题所建议的那样,唯一冻结的是控制台,那么记录消息并在后台记录消息的日志库,甚至使用缓冲区的日志库都不会受到影响。 - Panagiotis Kanavos
@PanagiotisKanavos:它只是感觉冻结了,但实际上并没有冻结。对于造成的困惑,我很抱歉,我的英语能力已经达到了极限。请随意编辑以使其更清晰。 - flayn
这是一个特性,而不是一个错误。与按下Ctrl+S时会出现的冻结类型没有什么不同。至少配置您的控制台,使其不那么容易被意外触发,按Alt+Space>属性>选项卡>取消选中“快速编辑模式”。 - Hans Passant
1个回答

4

正如此答案中所解释的那样,在此模式下,终端只是停止从应用程序输出中读取,这会导致您向该输出写入的内容(例如Console.WriteLine(...))挂起。

如果您控制编写到控制台的代码,则可以像这样实现您的目标(在检测到“冻结”时更改控制台标题):

static async Task WriteLine(string text) {            
    var delay = Task.Delay(TimeSpan.FromSeconds(1));
    var writeTask = Task.Run(() => Console.WriteLine(text));
    var oldTitle = Console.Title;
    if (await Task.WhenAny(delay, writeTask) == delay) {
        // after one second Console.WriteLine still did not return
        // we are probably in "mark and paste" mode
        Console.Title = "FREEZED!";
    }
    // we cannot ignore our write, have to wait anyway
    await writeTask;
    Console.Title = oldTitle;
} 

使用这种方法代替常规的Console.WriteLine。当然,这种方法的使用有限,但我认为它回答了你的问题。

您可以使用简单的方法进行测试:

static async Task Main(string[] args) {
    while (true) {
        await WriteLine("test");
        Thread.Sleep(1000);
    }
}

请注意,在这种模式下,控制台标题将更改为“FREEZED!”,当您退出该模式时,控制台标题将恢复原状。


我非常喜欢,谢谢!我会尝试一下。唯一的问题是:我认为在您的解决方案中,如果有很多内容写入控制台,则无法保证顺序。 - flayn
1
@flayn 这段代码是顺序执行的,只要你始终使用 await WriteLine("...") 就可以保证执行顺序。虽然它使用了 Task.Run,但这里并没有并行操作(请注意,在最后,Console.WriteLine 始终会与 await writeTask 一起被等待)。 - Evk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接