用并发队列(ConcurrentQueue)实现多线程任务中随时异步回调进度通知(.Net4.0)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//异步操作,代替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

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

posted on   Mainz  阅读(7464)  评论(7编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

统计

点击右上角即可分享
微信分享提示