这是一个挂起但永远不会结束的简单代码:
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
中风......
知道为什么会这样吗?我想运行一些后台任务并等到它在控制台应用程序中完成,但出于描述的原因,我的应用程序刚刚破解。
答案 0 :(得分:3)
问题不在于您的取消令牌,而是您选择使用CancelKeyPress
进行测试。发生此事件时,您将获得ConsoleCancelEventArgs
,其中包含Cancel
property:
获取或设置一个值,该值指示同时按下Control修饰键和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");
}