zoukankan      html  css  js  c++  java
  • .Net4.0并行库介绍——Cancellation Framework


    在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用。

    同步模式下的取消:

    一种比较常见的需要支持取消功能的的是一些比较耗时的分段操作:如视频转换,网络下载等,这种方式下的取消机制如下:

    1. 建立一个标记位,表示该操作是否已经取消
    2. UI线程在获取到取消事件后,置标记位为true
    3. 耗时的操作线程里,没进行一小段操作之后查询该标记位,如果为true则主动退出。

    使用方式如下:

        EventHandler externalEvent;
        void Example1()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            externalEvent +=
             (sender, obj) => { cts.Cancel(); }; //wire up an external requester
            try
            {
                int val = LongRunningFunc(cts.Token);
            }
            catch (OperationCanceledException)
            {
                //cleanup after cancellation if required...
            }
        }

        private static int LongRunningFunc(CancellationToken token)
        {
            int total = 0;
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                    total++;
                }
                if (token.IsCancellationRequested)
                { // observe cancellation
                    throw new OperationCanceledException(token); // acknowledge cancellation
                }
            }
            return total;
        }

    异步模式下的取消

    另外一种常见的方式是在一些异步操作中,往往不能主动释放,只能等待异步操作回调的时候才能操作结果。此时一般取消方法如下:

    1. 任务线程注册异步操作完成的回调函数,开始异步操作。
    2. UI线程接受取消指令,置取消标记位,并主动执行回调函数
    3. 回调函数中通过取消标记位判断该任务是已经完成还是被取消的,并执行相关析构操作。

    使用方式如下:

        void BlockingOperation(CancellationToken token)
        {
            ManualResetEvent mre = new ManualResetEvent(false);
            //register a callback that will set the MRE
            CancellationTokenRegistration registration =
             token.Register(() => mre.Set());
            using (registration)
            {
                mre.WaitOne();
                if (token.IsCancellationRequested) //did cancellation wake us?
                    throw new OperationCanceledException(token);
            } //dispose the registration, which performs the deregisteration.
        }

    这里我们通过CancellationToken注册了一个回调方法以通知任务等待线程,也可以以我们经常使用的WaitHandle的那样的方式使用。

        void Wait(WaitHandle wh, CancellationToken token)
        {
            WaitHandle.WaitAny(new[] { wh, token.WaitHandle });
            if (token.IsCancellationRequested) //did cancellation wake us?
                throw new OperationCanceledException(token);
        }

    高级应用

    由于例子比较简单,这里就只列举一下代码,不多介绍了。

    一个CancellationToken对应多个任务

        void Example4()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            Func1(cts.Token);
            Func2(cts.Token);
            Func3(cts.Token);
            //...
            cts.Cancel(); // all listeners see the same cancellation request.
        }

    一个任务对应多个CancellationToken

        void LinkingExample(CancellationToken ct1, CancellationToken ct2)
        {
            CancellationTokenSource linkedCTS =
            CancellationTokenSource.CreateLinkedTokenSource(ct1, ct2);
            try
            {
                SlowFunc(linkedCTS.Token);
            }
            catch (OperationCanceledException oce)
            {
                if (ct1.IsCancellationRequested)
                {
                    // ...
                }
                else if (ct2.IsCancellationRequested)
                {
                    // ...
                }
            }
            linkedCTS.Dispose(); // clean up the linking. required.
        }

    最后我们再来一个并发查询时取消的例子:

        private void RunQuery()
        {
            int[] data = { 1, 2, 3 };
            CancellationTokenSource cts = new CancellationTokenSource();
            var query = data.AsParallel()
                         .WithCancellation(cts.Token) // token given to library code
                         .Select((x) => SlowFunc(x, cts.Token)); // token passed to user code
        }

        private int SlowFunc(int x, CancellationToken token)
        {
         int result
         while(...)
         {
         if (token.IsCancellationRequested)
         throw new OperationCanceledException(token);
         ...
         }
         return result;
        }

    小结

    .net 4.0中的Cancellation Framework还是非常实用的,通过它可以更有效的简化及规范的使用各种取消的操作方式,由于我也只会皮毛,在这里也只是介绍了它的基本用法,在后续的学习和应用中将继续进一步介绍。

  • 相关阅读:
    答读者问(10):有关对博客的评价及个人技术发展路线等问题
    EasyUI学习之menu and button(菜单和按钮)
    二分查找
    【Android UI】色板
    很好的理解遗传算法的样例
    关于提高UDP发送效率的方法
    Log4cpp介绍及使用
    四个好看的CSS样式表格
    SpringMVC+easyUI 分页,查询 (完整的CRUD)
    [MODX] 1. Template *
  • 原文地址:https://www.cnblogs.com/TianFang/p/1596197.html
Copyright © 2011-2022 走看看