下面是挂起并永不结束的简单代码片段:
public static void Main()
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
Console.CancelKeyPress += (_, __) =>
cancellationTokenSource.Cancel();
while (!cancellationTokenSource.Token.WaitHandle.WaitOne(1000))
{
Console.WriteLine("Still running...");
}
Console.WriteLine("Cancellation is requested. Trying to dispose cancellation token...");
}
Console.WriteLine("Just before close");
}问题是Just before close行永远不会被执行。我的第一个想法是“可能是因为关闭了KeyPress”,所以我用以下方式重写了它:
public static void Main()
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
void Foo(object sender, ConsoleCancelEventArgs consoleCancelEventArgs)
{
cancellationTokenSource.Cancel();
}
Console.CancelKeyPress += Foo;
while (!cancellationTokenSource.Token.WaitHandle.WaitOne(1000))
{
Console.WriteLine("Still running...");
}
Console.WriteLine("Cancellation is requested. Unsubscribing...");
Console.CancelKeyPress -= Foo;
Console.WriteLine("Cancellation is requested. Trying to dispose cancellation token...");
}
Console.WriteLine("Just before close");
}但现在它挂在Unsubscribing中风上..。
知道为什么会这样吗?我想运行一些后台任务,直到它在控制台应用程序完成,但由于描述的原因,我的应用程序刚刚坏了。
发布于 2018-03-28 14:27:48
问题不是取消令牌,而是您选择使用CancelKeyPress进行测试。当此事件发生时,您将得到ConsoleCancelEventArgs,它有一个 property
获取或设置一个值,该值指示同时按“控制修饰符”键和C控制台键(Ctrl+C)或Ctrl+Break键是否终止当前进程。默认值为false,这将终止当前进程。
由于您没有将其设置为true,所以您的应用程序在事件处理程序完成运行后终止。具体取决于当时发生了什么,有时取消令牌似乎有时间脱离while循环,而其他时候则没有:

您的原始代码可以按以下方式修正:
public static void Main()
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
Console.CancelKeyPress += (_, ccea) => {
cancellationTokenSource.Cancel();
ccea.Cancel = true; //cancel the cancel. There's too many cancels!
};
while (!cancellationTokenSource.Token.WaitHandle.WaitOne(1000))
{
Console.WriteLine("Still running...");
}
Console.WriteLine("Cancellation is requested. Trying to dispose cancellation token...");
}
Console.WriteLine("Just before close");
}https://stackoverflow.com/questions/49537037
复制相似问题