.Net C# CancellationToken 取消令牌

在进行异步开发或者使用Task类设计并行任务时,通常都会遇到在达成某些条件时终止任务,这时我们可以使用 取消令牌(CancellationToken)来协助我们完成这项工作。

令牌创建:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;

令牌使用(通过对应重载方法传入):

Task t = Task.Run(() => Task.Delay(5000, token), token);

await Task.Delay(1000, token);

取消任务:

//第一种方法
var timespan = new TimeSpan(0, 0, 0, 4);//设置超时时间
tokenSource.CancelAfter(timespan);
//第二种方法
tokenSource.Cancel();

CancelAfter方法还有整型(int)入参的重载方法,Cancel方法可以传入布尔类型(bool)参数指定是否立即弹出异常。

在一个任务中需要使用多个取消令牌(多种条件)的情况下可以使用CreateLinkedTokenSource方法。

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationTokenSource tokenSource1 = new CancellationTokenSource();
CancellationTokenSource cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token,tokenSource1.Token);

在任务取消后,我们可能需要做一下额外的工作,比如说通知任务已经取消,CancellationToken.Register方法用来处理取消后的回调操作。我们传入一个委托即可。

CancellationToken token = tokenSource.Token;
token.Register(() => Console.WriteLine("任务取消!这里是回调函数。"));

取消任务时我们可以在方法内通过token.IsCancellationRequested属性判断任务是否取消,也可以使用token.ThrowIfCancellationRequested()方法直接引发异常。

参考代码:

class CancelTesk
    {
        public async static Task CancelTeskMain()
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationTokenSource tokenSource1 = new CancellationTokenSource();
            CancellationTokenSource cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token, tokenSource1.Token);
            var timespan = new TimeSpan(0, 0, 0, 4);//设置超时时间
            tokenSource.CancelAfter(timespan);
            try
            {
                CancellationToken token = tokenSource.Token;
                token.Register(() => Console.WriteLine("任务取消!这里是回调函数。"));

                Console.WriteLine(DateTimeOffset.Now);

                //输出token状态
                Console.WriteLine($"输出token状态:{token.IsCancellationRequested}");

                Task t = Task.Run(() => Task.Delay(5000, token), token);

                Task t2 = Task.Run(() => TaskRun(token), token);

                await Task.Delay(2000, token);

                //输出任务是否取消
                Console.WriteLine($"输出任务是否取消{t.IsCanceled},{t.Status}");

                //取消任务
                tokenSource.Cancel();

                //await Task.WhenAll(t);

                t2.Wait();

                //输出token状态
                Console.WriteLine($"输出token状态:{token.IsCancellationRequested}");

                //输出任务是否取消
                Console.WriteLine($"输出任务是否取消{t.IsCanceled},{t.Status}");

                Console.WriteLine("结束任务");
            }
            catch (OperationCanceledException oex)
            {
                Console.WriteLine($"取消任务引发异常:{oex}");
            }
            catch (AggregateException aex)
            {
                Console.WriteLine($"取消任务引发异常:{aex}");
            }
            catch (Exception ex)
            {

                throw;
            }
        }

        private static Task TaskRun(CancellationToken token)
        {

            try
            {
                //判断任务是否取消通过 token.IsCancellationRequested
                while (!token.IsCancellationRequested)
                {
                    //取消时直接引发异常
                    token.ThrowIfCancellationRequested();

                    Console.WriteLine("执行任务" + token.IsCancellationRequested);

                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("跳出结束任务");
                        break;
                    }

                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("任务执行异常:" + ex);

            }

            Console.WriteLine("退出循环,输出token状态:" + token.IsCancellationRequested);

            return Task.CompletedTask;
        }
    }

输出结果:

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个堆栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值