C# CancellationTokenSource。Cancel正在引发异常

C# CancellationTokenSource。Cancel正在引发异常,c#,.net,task,wait,cancellationtokensource,C#,.net,Task,Wait,Cancellationtokensource,在阅读文档CancellationTokenSource时,Cancel不应引发异常。 下面是对cts.Cancel()的调用;正在导致(而不是引发)OperationCanceledException。 我很有信心,就好像我把这行注释掉了一样,那么最后一个OperationCanceledException就不会被抛出 当cts.Cancel行处于活动状态时,引发异常的行是t2.Wait(令牌) 如果我在cts中有延迟,取消();然后t2.等待(令牌);不会在调用该行时立即引发异常。 t2.

在阅读文档CancellationTokenSource时,Cancel不应引发异常。

下面是对cts.Cancel()的调用;正在导致(而不是引发)OperationCanceledException。
我很有信心,就好像我把这行注释掉了一样,那么最后一个OperationCanceledException就不会被抛出

当cts.Cancel行处于活动状态时,引发异常的行是t2.Wait(令牌)
如果我在cts中有延迟,取消();然后t2.等待(令牌);不会在调用该行时立即引发异常。
t2.等待(令牌);仅在运行cts.Cancel()时引发该异常。
这是正确的行为吗?
如果它是一致的,那么我可以接受它,但我不希望cts.Cancel导致异常。
我显然很困惑——我只是想了解这种行为,这样我就可以放心地将其带到生产环境中。
现在我正在和一个后台工作人员一起做这件事,我想我可以使用wait和cancel使跟踪和维护变得更容易

如果(token.IsCancellationRequested | | ctr==100000000)
仍然抛出ctr==100000000
我仍然看到内部操作CanceledException被捕获,而外部(下部)根本没有抛出

此代码是否有问题?
还是应该这样做

如果没有任务t2=Task.Run中的try-catch,则会引发未捕获的异常。
我以为这会被t2上的试抓抓到。等一下,每次只问一个问题

这是.NET4.5上的控制台应用程序

static void Main(string[] args)
{
    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken token = cts.Token;

    Task.Run(() =>
    {
        Thread.Sleep(1000);
        cts.Cancel();  // this is thowing an exception that is caught on the last catch (OperationCanceledException Ex)
        // according to the documentation this is not supposed
        // if I comment out the cts.Cancel(); then the exeption is not thrown
        if (token.IsCancellationRequested)
            Console.WriteLine("Cancellation requested in Task {0}.",
                                Task.CurrentId);
        else
            Console.WriteLine("Cancellation Not requested in Task {0}.",
                                Task.CurrentId);

    }, token);

    //tried this but did not help
    //Task.Run(() =>
    //{
    //    //Thread.Sleep(1000);
    //    if (token.IsCancellationRequested)
    //        Console.WriteLine("Cancellation requested in Task {0}.",
    //                            Task.CurrentId);
    //}, token);
    //Thread.Sleep(1000);
    ////cts.Cancel();


    Task t2 = Task.Run(() =>
    {
        try
        {
            Console.WriteLine("Task t2 started Int32.MaxValue = " + Int32.MaxValue.ToString());
            Thread.Sleep(4000);
            for (int ctr = 0; ctr < Int32.MaxValue; ctr++)
            {
                if (ctr < 100 || ctr % 100000000 == 0)
                {
                    Console.WriteLine(ctr.ToString());

                }
                if (token.IsCancellationRequested || ctr == 100000000)  //  || ctr == 100000000
                {
                    Console.WriteLine("ThrowIfCancellationRequested in t2 Task  {0}.",
                                Task.CurrentId);
                    throw new OperationCanceledException(token);
                    //token.ThrowIfCancellationRequested();
                }
            }
            Console.WriteLine("Task {0} finished.",
                            Task.CurrentId);
        }
        catch (OperationCanceledException Ex)
        {
            //Console.WriteLine(Ex.ToString());
            Console.WriteLine("OperationCanceledException in Task t2 {0}: The operation was cancelled.",
                                Task.CurrentId);
        }
        catch (Exception Ex)
        {
            Console.WriteLine("Task t2 = Task.Run Exception Ex" + Ex.Message);
        }               
    });
    try
    {
        Console.WriteLine("t2.Wait a");
        t2.Wait(token);
    }
    catch (AggregateException e)
    {
        Console.WriteLine("AggregateException");
        foreach (var v in e.InnerExceptions)
            Console.WriteLine(e.Message + " " + v.Message);
    }
    catch (OperationCanceledException Ex)
    {
        //Console.WriteLine(Ex.ToString());
        Console.WriteLine("OperationCanceledException in Task {0}: The operation was cancelled.",
                            t2.Id);
    }
    catch (Exception Ex)
    {
        Console.WriteLine(Ex.ToString());
    }
    Console.WriteLine("end");
    Console.ReadLine();
}
static void Main(字符串[]args)
{
CancellationTokenSource cts=新的CancellationTokenSource();
CancellationToken=cts.token;
Task.Run(()=>
{
睡眠(1000);
cts.Cancel();//这是上次捕获时捕获的异常(OperationCanceledException Ex)
//根据文件,这是不应该的
//如果我注释掉cts.Cancel();则不会抛出exeption
if(令牌.IsCancellationRequested)
WriteLine(“在任务{0}中请求取消。”,
Task.CurrentId);
其他的
WriteLine(“在任务{0}中未请求取消。”,
Task.CurrentId);
},代币);
//尝试了这个,但没有帮助
//Task.Run(()=>
//{
////Thread.Sleep(1000);
//if(令牌.IsCancellationRequested)
//WriteLine(“在任务{0}中请求取消。”,
//Task.CurrentId);
//},代币);
//睡眠(1000);
////cts.Cancel();
任务t2=任务。运行(()=>
{
尝试
{
Console.WriteLine(“任务t2开始于Int32.MaxValue=“+Int32.MaxValue.ToString());
睡眠(4000);
对于(int-ctr=0;ctr
我可能错了,但您之所以出现此异常,是因为您正在取消放置cancel语句的同一任务。operationCanceledException MSDN文档说明如下:-

在取消线程正在执行的操作时在线程中引发的异常

是否可以尝试将第一个任务调用修改为以下内容,并检查是否仍然出现异常:-

Task.Run(() =>
    {
        Thread.Sleep(1000);
        if (token.IsCancellationRequested)
            Console.WriteLine("Cancellation requested in Task {0}.",
                                Task.CurrentId);
    }, token);
cts.Cancel();
taskCancellationSource的有用链接:-


是的,这是预期的行为: 使用取消令牌的
任务.Wait
的重载将一直等到:

  • 您正在等待的任务已完成
  • 传入的取消令牌被取消
在后一种情况下,当
Task.Wait
观察到传入的令牌已被取消时,它抛出一个“OperationCancelledException”。这是在您的案例中触发异常时的调用堆栈

    mscorlib.dll!System.Threading.CancellationToken.ThrowOperationCanceledException() Line 505 + 0x4d bytes C#
    mscorlib.dll!System.Threading.ManualResetEventSlim.Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) Line 642 C#
    mscorlib.dll!System.Threading.Tasks.Task.SpinThenBlockingWait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) Line 3284 + 0xf bytes  C#
    mscorlib.dll!System.Threading.Tasks.Task.InternalWait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) Line 3223 + 0x10 bytes C#
    mscorlib.dll!System.Threading.Tasks.Task.Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) Line 3129 + 0xc bytes  C#
    mscorlib.dll!System.Threading.Tasks.Task.Wait(System.Threading.CancellationToken cancellationToken) Line 3064 + 0xe bytes   C#
>   ConsoleApplication1.exe!ConsoleApplication1.Program.Main(string[] args) Line 82 + 0x15 bytes    C#
关于问题的第二部分: 如果你 -在t2和t2内移除了try/catch -你从未取消过代币

然后,您将在外部
AggregateException
处理程序中着陆(因为对
t2.Wait
的调用将抛出一个
AggregateException
和一个inne)
cts.Cancel();