C# 异步方法async / await 任务超时处置惩罚

打印 上一主题 下一主题

主题 1011|帖子 1011|积分 3033

一、需求

假如调用一个异步方法后,一直不给返回值结果怎么办呢?这就涉及到怎么取消任务了。

二、Task取消任务

  1. static CancellationTokenSource source = new CancellationTokenSource();
  2. static void Main(string[] args)
  3. {
  4.      Task.Run(() =>
  5.      {
  6.          for (int i = 0; i < 10; i++)
  7.          {
  8.              Thread.Sleep(500);
  9.              Console.WriteLine("oh my god");
  10.              source.Token.ThrowIfCancellationRequested();
  11.          }
  12.      }, source.Token);
  13.      Thread.Sleep(2000);
  14.      Console.WriteLine("取消任务");
  15.      source.Cancel();
  16.      Console.ReadKey();
  17. }
复制代码

换一个写法
  1.         static void Main(string[] args)
  2.         {
  3.             bool isOut = false;
  4.             var task1 = Task.Run(() =>
  5.             {
  6.                 for (int i = 0; i < 100; i++)
  7.                 {
  8.                     if (isOut) return;
  9.                     Console.WriteLine("执行中" + i);
  10.                     Thread.Sleep(500);
  11.                 }
  12.             });
  13.             Thread.Sleep(2000);
  14.             Console.WriteLine("取消任务");
  15.             isOut = true;
  16.             Console.ReadKey();
  17.         }
复制代码
 我在 for 循环中加入一个判断,假如等于 true,直接跳出循环,这不也可以中断任务



三、Task取消任务的回调

取消任务也是可以加入回调的,如下:
  1. static CancellationTokenSource source = new CancellationTokenSource();
  2. static void Main(string[] args)
  3. {
  4.      var task1 = Task.Run(() =>
  5.      {
  6.          for (int i = 0; i < 100; i++)
  7.          {
  8.              source.Token.ThrowIfCancellationRequested();
  9.              Console.WriteLine("执行中" + i);
  10.              Thread.Sleep(500);
  11.          }
  12.      }, source.Token);
  13.      //在指定的毫秒数后取消task执行
  14.      source.CancelAfter(2 * 1000);
  15.      //取消任务后的回调
  16.      source.Token.Register(() =>
  17.      {
  18.          //不延迟会获取不到正确的状态
  19.          Thread.Sleep(50);
  20.          Console.WriteLine("task1状态:" + task1.Status);
  21.          Console.WriteLine("IsFaulted状态:" + task1.IsFaulted);//由于未处理的异常,任务已完成。
  22.          Console.WriteLine("IsCompleted状态:" + task1.IsCompleted);//获取一个值,该值指示任务是否已完成。
  23.      });
  24.      Console.ReadKey();
  25. }
复制代码



四、Task超时处置惩罚的实现


先来一个超时取消后续代码实验的方法


  1. private static CancellationTokenSource Cancellation = new CancellationTokenSource();
  2. static void Main(string[] args)
  3. {
  4.      //设置超时的时间
  5.      Cancellation.CancelAfter(TimeSpan.FromSeconds(1));
  6.      Task.Run(() =>
  7.      {
  8.          try
  9.          {
  10.              Console.WriteLine("方法执行开始");
  11.              //异步 Task.Delay 可以这么写,await Task.Delay(3000, Cancellation.Token)
  12.              //效果同 Cancellation.Token.ThrowIfCancellationRequested()
  13.              //await Task.Delay(3000, Cancellation.Token);
  14.              Thread.Sleep(2000);
  15.              Cancellation.Token.ThrowIfCancellationRequested();
  16.              Console.WriteLine("方法执行结束");
  17.          }
  18.          catch (OperationCanceledException)
  19.          {
  20.              Console.WriteLine("取消操作");
  21.          }
  22.      });
  23.      Console.ReadKey();
  24. }
复制代码

可以看到,方法实验结束这段代码并没有打印,这就是我们想要的结果了,在上面我们设置的超时时间是1秒,在后面的实验中,使用了线程睡眠时间是2秒,超时后,就主动取消操作了


把超时时间改为3秒,看看结果
  1. private static CancellationTokenSource Cancellation = new CancellationTokenSource();
  2. static void Main(string[] args)
  3. {
  4.     //设置超时的时间
  5.     Cancellation.CancelAfter(TimeSpan.FromSeconds(3));
  6.     Task.Run(() =>
  7.     {
  8.         try
  9.         {
  10.             Console.WriteLine("方法执行开始");
  11.             //异步 Task.Delay 可以这么写,await Task.Delay(3000, Cancellation.Token)
  12.             //效果同 Cancellation.Token.ThrowIfCancellationRequested()
  13.             //await Task.Delay(3000, Cancellation.Token);
  14.             Thread.Sleep(2000);
  15.             Cancellation.Token.ThrowIfCancellationRequested();
  16.             Console.WriteLine("方法执行结束");
  17.         }
  18.         catch (OperationCanceledException)
  19.         {
  20.             Console.WriteLine("取消操作");
  21.         }
  22.     });
  23.     Console.ReadKey();
  24. }
复制代码

这回就没有取消任务的实验了,那么超时取消代码实验的结果就实现了。







免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

道家人

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表