zoukankan      html  css  js  c++  java
  • 用并发队列(ConcurrentQueue)实现多线程任务中随时异步回调进度通知(.Net4.0)

    本文讲述实现抽象出来的异步通知回调进度通知,用在多层组件中,支持一组task的任意进度回调通知。本文中用到几个.NET 4.0的新方法和TPL方法:TupleConcurrentQueueSemaphoreSlimTask...说明:如果你是一个简单的Task可能无需这么复杂,用传入Action同步回调即可,但是注意NotifyProgress也就是在任务执行过程中随时同步通知进度,会造成你任务阻塞。如果你是在UI层,用BackgroundWorkder最简单了。(本文原创http://mainz.cnblogs.com,转载请注明。)

       //异步操作,代替Thread, threadPool
       Task _ProgressQueueTask = null;
       //限制并发访问资源的线程数,SemaphoreSlim开销低于Semaphore50倍
       SemaphoreSlim _ProgressCounter = null;
       //并发队列ConcurrentQueue,线程安全的队列
       //Tuple:元数据结构,可以方便的访问其item
       ConcurrentQueue<tuple<progressaction, string,="" int?="">> _ProgressQueue = new ConcurrentQueue<tuple<progressaction, string,="" int?="">>();
       Action<progressaction, string,="" int?=""> _OnProgress;
         public Action<progressaction, string,="" int?=""> OnProgress
         {
             get {  return _OnProgress; }
             set
            {
               _OnProgress = value;
               if (_ProgressQueueTask == null)
               {
                       _ProgressQueueTask = new Task(() =>
                       {
                              while (true)
                               {
                                   Tuple<progressaction, string,="" int?=""> item;
                                   //查询队列
                                   if (_ProgressQueue.TryDequeue(out item))
                                   {
                                       OnProgress(item.Item1, item.Item2, item.Item3);
                                   }
                                   else
                                   {
                                       //线程等待信号,由NotifyProgress入队列并给予信号
                                       _ProgressCounter.Wait();
                                   }
                               }
                           },
                           TaskCreationOptions.LongRunning);
                    _ProgressCounter = new SemaphoreSlim(0, 10);//初始0,最大限制10
                       _ProgressQueueTask.Start();
                   }
               }
           }
           //在任何Task的执行过程中,或一组task的执行过程中,可以调用此方法来异步回调随时通知进度,而不会阻塞本任务
           public void NotifyProgress(ProgressAction action, string item = null, long? current = null, long? maxCount = null)
           {
               if (OnProgress != null)
               {
                   int? percent = null;
                   if (current.HasValue && maxCount.HasValue)
                   {
                       percent = (int)((double)current.Value / (double)maxCount.Value * 100.0);
                   }
                   _ProgressQueue.Enqueue(Tuple.Create(action, item, percent));
                   _ProgressCounter.Release();
               }
               return;
           }
          public enum ProgressAction
          {
                   Adding,
                   Extracting,
                   Extracted,
                   Validating,
                   Validated,
                   Deleting,
                   Deleted,
                   Restore
          };
           //用法:
           //中间层
           NotifyProgress(ProgressAction.Extracting, "abc");
           //界面层
           OnProgress = (action, file, percent) =>
                       {  
                              //...
                        }
    

    10.13

    有问题请回复。本文结束,代码带注释。

  • 相关阅读:
    [转]JAVA程序执行顺序,你了解了吗:JAVA中执行顺序,JAVA中赋值顺序
    [转]浅谈Java中的equals和==
    [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
    [原创]java WEB学习笔记101:Spring学习---Spring Bean配置:IOC容器中bean的声明周期,Bean 后置处理器
    C# 数组之List<T>
    C# 数组之ArrayList
    C# 数组之int[]
    reverse-XNUCA-babyfuscator
    reverse-daily(1)-audio_visual_receiver_code
    Python多线程和多进程谁更快?
  • 原文地址:https://www.cnblogs.com/Mainz/p/2209924.html
Copyright © 2011-2022 走看看