.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;
        }
    }

输出结果:

.Net C# CancellationToken 取消令牌_第1张图片

 

你可能感兴趣的:(.Net,C#,.net,c#,microsoft)