Ale*_*kiy 2 .net c# asynchronous task
这是挂起且永不结束的简单代码段:
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");
}
Run Code Online (Sandbox Code Playgroud)
问题是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");
}
Run Code Online (Sandbox Code Playgroud)
但现在它挂在Unsubscribing中风......
知道为什么会这样吗?我想运行一些后台任务并等到它在控制台应用程序中完成,但由于描述的原因,我的应用程序刚刚损坏。
问题不在于您的取消令牌,而在于您选择使用CancelKeyPress. 当这个事件发生时,你会得到ConsoleCancelEventArgs,它有一个Cancel属性:
获取或设置一个值,该值指示是否同时按下 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");
}
Run Code Online (Sandbox Code Playgroud)