zoukankan      html  css  js  c++  java
  • Task:取消异步计算限制操作 & 捕获任务中的异常

    Why:ThreadPool没有内建机制标记当前线程在什么时候完成,也没有机制在操作完成时获得返回值,因而推出了Task,更精确的管理异步线程。

    How:通过构造方法的参数TaskCreationOptions控制如何创建任务,具体查看该枚举的枚举值。获取任务执行的结果有Task.Result属性,该属性内部调用wait(),例如WaitAny()、WaitAll()等等都可以。

    如何取消异步计算限制操作呢?也就是说如何取消执行中的任务呢?(鄙视clr的作者用“计算限制操作”这么复杂的词汇。)

    例化CancelletionTokenSource类,把该对象作为参数传给异步方法,在异步方法中调用该对象的ThrowIfCancellationRequested(),如果该对象的Cancel()方法被调用了,那么异步方法就会抛出异常OperationCanceledException,在主线程用try-catch进行捕获(AggregateException),就可以捕获异常并进行处理。

     class Program
        {
            static void Main(string[] args)
            {
                CancellationTokenSource cts = new CancellationTokenSource();//CancellationTokenSource(3000);//3秒后没有得到结果,则取消该线程。
                Task<Int32> t1 = Task.Run(() => sum(cts.Token, 10000), cts.Token);//传入CancellationToken,它是CancellationTokenSource的属性。
                cts.Cancel();//cts.CancelAfter(3000);//3秒后如果没有得到结果,则取消该线程。
                try
                {
                    Console.WriteLine("t1执行的结果是:" + t1.Result);//通过Result获取t1的执行结果。
                }
                catch (AggregateException ex)
                {
                    ex.Handle(e => e is OperationCanceledException);
                    Console.WriteLine("sum已经被取消");
                }
                Console.ReadKey();
            }
    
            private static int sum(CancellationToken ct, int p)
            {
                int sum = 0;
                while (p > 0)
                {
                    ct.ThrowIfCancellationRequested();
                    Thread.Sleep(500);//每隔半秒累加一次。
                    checked//如果区域内的计算溢出就会抛出异常
                    {
                        sum += p;
                    }
                    p--;
                }
                return sum;
            }
    }

    运行结果:sum已经被取消

    成功的捕获到了异常并处理了。

    但是我发现有一个地方我不能理解

    1、如果是通过CancellationTokenSource的构造方法public CancellationTokenSource(int millisecondsDelay);构造的实例对象,try-catch捕获不到异常。

    2、如果是通过CanelAfter(TimeSpan delay)取消,也捕获不到异常。

    通过ILSpy我发现上诉构造方法和CanelAfter方法都是调用Cancel()方法,但是为何捕获不到异常呢?

    我进一步查看ThrowIfCancellationRequested源码

    public void ThrowIfCancellationRequested()
            {
                if (this.IsCancellationRequested)
                {
                    this.ThrowOperationCanceledException();
                }
            }

    然而并没有什么卵用,因为只要把下图中的设置取消,即可捕获到了异常。

  • 相关阅读:
    详解JVM中的内存模型是什么?
    【亲测】手把手教你如何破解pycharm(附安装包和破解文件)
    Spring实战第4版PDF下载含源码
    Tomcat的基本使用及相关知识的概述(超详细版)
    JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !
    详解JVM中的五大内存区域
    [Django][python][工具]阿里云平台短信验证功能
    [数据分析][评价方法]打分式评价-信息熵理论与熵权法
    [工具]用OmniGraffle 五步绘制流程图
    [操作系统]设备分配中的数据结构:设备控制表(DCT)、控制器控制表(COCT)、通道控制表(CHCT)和系统设备表(SDT)
  • 原文地址:https://www.cnblogs.com/kexxxfeng/p/4629353.html
Copyright © 2011-2022 走看看