• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

.Net C# CancellationToken 取消令牌

武飞扬头像
一个堆栈
帮助1

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

令牌创建:

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

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

  1.  
    Task t = Task.Run(() => Task.Delay(5000, token), token);
  2.  
     
  3.  
    await Task.Delay(1000, token);

取消任务:

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

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

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

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

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

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

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

参考代码:

  1.  
    class CancelTesk
  2.  
    {
  3.  
    public async static Task CancelTeskMain()
  4.  
    {
  5.  
    CancellationTokenSource tokenSource = new CancellationTokenSource();
  6.  
    CancellationTokenSource tokenSource1 = new CancellationTokenSource();
  7.  
    CancellationTokenSource cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token, tokenSource1.Token);
  8.  
    var timespan = new TimeSpan(0, 0, 0, 4);//设置超时时间
  9.  
    tokenSource.CancelAfter(timespan);
  10.  
    try
  11.  
    {
  12.  
    CancellationToken token = tokenSource.Token;
  13.  
    token.Register(() => Console.WriteLine("任务取消!这里是回调函数。"));
  14.  
     
  15.  
    Console.WriteLine(DateTimeOffset.Now);
  16.  
     
  17.  
    //输出token状态
  18.  
    Console.WriteLine($"输出token状态:{token.IsCancellationRequested}");
  19.  
     
  20.  
    Task t = Task.Run(() => Task.Delay(5000, token), token);
  21.  
     
  22.  
    Task t2 = Task.Run(() => TaskRun(token), token);
  23.  
     
  24.  
    await Task.Delay(2000, token);
  25.  
     
  26.  
    //输出任务是否取消
  27.  
    Console.WriteLine($"输出任务是否取消{t.IsCanceled},{t.Status}");
  28.  
     
  29.  
    //取消任务
  30.  
    tokenSource.Cancel();
  31.  
     
  32.  
    //await Task.WhenAll(t);
  33.  
     
  34.  
    t2.Wait();
  35.  
     
  36.  
    //输出token状态
  37.  
    Console.WriteLine($"输出token状态:{token.IsCancellationRequested}");
  38.  
     
  39.  
    //输出任务是否取消
  40.  
    Console.WriteLine($"输出任务是否取消{t.IsCanceled},{t.Status}");
  41.  
     
  42.  
    Console.WriteLine("结束任务");
  43.  
    }
  44.  
    catch (OperationCanceledException oex)
  45.  
    {
  46.  
    Console.WriteLine($"取消任务引发异常:{oex}");
  47.  
    }
  48.  
    catch (AggregateException aex)
  49.  
    {
  50.  
    Console.WriteLine($"取消任务引发异常:{aex}");
  51.  
    }
  52.  
    catch (Exception ex)
  53.  
    {
  54.  
     
  55.  
    throw;
  56.  
    }
  57.  
    }
  58.  
     
  59.  
    private static Task TaskRun(CancellationToken token)
  60.  
    {
  61.  
     
  62.  
    try
  63.  
    {
  64.  
    //判断任务是否取消通过 token.IsCancellationRequested
  65.  
    while (!token.IsCancellationRequested)
  66.  
    {
  67.  
    //取消时直接引发异常
  68.  
    token.ThrowIfCancellationRequested();
  69.  
     
  70.  
    Console.WriteLine("执行任务" token.IsCancellationRequested);
  71.  
     
  72.  
    if (token.IsCancellationRequested)
  73.  
    {
  74.  
    Console.WriteLine("跳出结束任务");
  75.  
    break;
  76.  
    }
  77.  
     
  78.  
    Thread.Sleep(1000);
  79.  
    }
  80.  
    }
  81.  
    catch (Exception ex)
  82.  
    {
  83.  
    Console.WriteLine("任务执行异常:" ex);
  84.  
     
  85.  
    }
  86.  
     
  87.  
    Console.WriteLine("退出循环,输出token状态:" token.IsCancellationRequested);
  88.  
     
  89.  
    return Task.CompletedTask;
  90.  
    }
  91.  
    }
学新通

输出结果:

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggbifg
系列文章
更多 icon
同类精品
更多 icon
继续加载