CancellationTokenSourcedoesnotbehaviorasexpected在这种情况下,预期的是,如果用户通过按Enter键取消任务,则由ContinueWith挂钩的另一个任务将运行,但在事实上并非如此,因为尽管ContinueWith未明确处理,但AggregateException仍在执行。对以下有任何澄清吗?类程序{staticvoidMain(string[]args){CancellationTokenSourcetokensource=newCancellationTokenSource();CancellationTokentoken=tokensource.Token;Tasktask=Task.Run(()=>{while(!token.IsCancellationRequested){Console.Write("*");Thread.Sleep(1000);}},token).ContinueWith((t)=>{t.Exception.Handle((e)=>true);Console.WriteLine("你已经取消了任务");},TaskContinuationOptions.OnlyOnCanceled);Console.WriteLine("按任意键取消");控制台.ReadLine();tokensource.Cancel();任务.等待();让我们从一些事实开始吧:当您将CancellationToken作为参数传递给Task.Run时,只有在任务开始运行之前取消它才会生效。如果任务已经在运行,则不会被取消。要在开始运行后取消任务,您需要使用CancellationToken.ThrowIfCancellationRequested,而不是CancellationToken.IsCancellationRequested。如果任务被取消,其Exception属性将不包含任何异常并且将为空。如果延续由于某种原因没有运行,它会被取消。任务包含自身及其所有子任务的异常(因此,AggregateException)。这就是您的代码中发生的情况:任务开始运行,因为令牌未被取消。它将一直运行直到令牌被撤销。结束后,延续将不会运行,因为它仅在上一个任务取消时运行,但尚未取消。当您等待任务时,它将抛出带有TaskCanceledException的AggregateException,因为延续已被取消(如果您删除延续,异常将消失)。解决方案:您需要修复任务,使其实际上被取消,并删除(或空检查)异常处理,因为没有异常:vartask=Task.Run(newAction(()=>{while(true){token.ThrowIfCancellationRequested();Console.Write("*");Thread.Sleep(1000);}}),token).ContinueWith(t=>Console.WriteLine("你已经取消了任务"),TaskContinuationOptions.OnlyOnCanceled);如果您将令牌作为第二个参数传递,则任务将无法正常继续,因为它确实已被取消。相反,它会抛出一个OperationCanceledException,它包含在一个AggregateException中。这完全是意料之中的。现在,如果您不将令牌传递给任务构造函数,那么您将看到预期的行为,因为您只是使用令牌作为退出while循环的标志。在这种情况下,您实际上并没有取消任务,而是退出while循环并正常完成任务。以上是C#学习教程:CancellationTokenSource的行为不符合预期的所有内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处:
