这是一个挂起且永不结束的简单代码片段:
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
中风...
知道为什么会这样吗?我想运行一些后台任务并等待它在控制台应用程序中完成,但由于上述原因,我的应用程序刚刚损坏。
最佳答案
问题不是您的取消 token ,而是您选择使用 CancelKeyPress
进行测试的事实。当此事件发生时,您将获得 ConsoleCancelEventArgs
,它有一个 Cancel
property :
Gets or sets a value that indicates whether simultaneously pressing the Control modifier key and the C console key (Ctrl+C) or the Ctrl+Break keys terminates the current process. The default is false, which terminates the current process.
由于您没有将其设置为 true
,您的应用程序将在事件处理程序完成运行后终止。根据当时发生的具体情况,似乎有时取消 token 有时间跳出 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");
}
关于c# - 为什么CancellationTokenSource挂了一个应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49537037/