为什么该任务没有完成?

时间:2019-01-25 18:29:00

标签: c#

为什么在按Ctrl + C时不退出此控制台应用程序?

程序输出:

Press Ctrl+C to stop...
doing stuff.
doing stuff.
...
*Ctrl+C pressed*
exiting...
*never actually exits*

class Program {
    static void Main(string[] args) {
        MainAsync(args).GetAwaiter().GetResult();
    }

    private static async Task MainAsync(string[] args) {

        MyAsyncClass myAsync = new MyAsyncClass();

        var tcs = new TaskCompletionSource<object>();
        Console.CancelKeyPress += (sender, e) => { tcs.SetResult(null); };

        var task = Task.Run(() => myAsync.Start());

        await Console.Out.WriteLineAsync("Press Ctrl+C to stop...");

        await tcs.Task;
        await Console.Out.WriteLineAsync("exiting...");
    }
}

public class MyAsyncClass {
    public async Task Start() {
        while(true) {
            await Console.Out.WriteLineAsync("doing stuff.");
            Thread.Sleep(1000);
        }
    }
}

1 个答案:

答案 0 :(得分:-1)

您需要将ConsoleCancelEventArgs.Cancel属性设置为true

Console.CancelKeyPress += (sender, e) =>
{
    tcs.SetResult(null);
    e.Cancel = true;   // <-------- add this to your code
};

这将使您的代码继续到程序末尾并正常退出,而不是Ctrl+C来在事件处理程序完成后尝试终止应用程序。

请注意,在测试中,我发现这仅在附加Visual Studio调试器(使用F5运行)时才有意义。但是,在没有附加任何附件(Ctrl+F5的情况下运行,或者仅运行已编译的.exe)似乎并不在乎是否设置了此属性。我找不到任何能解释为什么会出现这种情况的信息,但我想是有某种竞争情况在发生。

最后,将CancellationToken传递到您的myAsync.Start方法中并使用它代替while(true)是一个很好的形式。最好使用await Task.Delay代替Thread.Sleep(但这些都不是问题的根源)。

相关问题