C# 自定义固定数量线程池

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace A9AgentApp.Task
{
    public class CustomThread
    {
        #region Variable
        //一个AutoResetEvent实例
        private AutoResetEvent _locks = new AutoResetEvent(false);
 
        //一个Thread实例
        private Thread _thread;
 
        // 绑定回调方法,就是外部实际执行的任务
        public WaitCallback _taskAction;
 
        //定义一个事件用来绑定工作完成后的操作
        public event Action<CustomThread> WorkCompleted;
 
        /// <summary>
        ///设置线程拥有的Key
        /// </summary>
        public string Key { get; set; }
 
        /// <summary>
        /// 当前线程消息输出Action
        /// </summary>
        public Action<String> MessageWriterAction;
        #endregion
 
        //线程需要做的工作
        private void Work()
        {
            while (true)
            {
                //判断信号状态,如果有set那么 _locks.WaitOne()后的程序就继续执行
                _locks.WaitOne();
                // 将当前线程实例传到Action里
                _taskAction(this);
                // Console.WriteLine("Thread:" + Thread.CurrentThread.ManagedThreadId + "workComplete");
                //执行完成事件
                WorkCompleted(this);
            }
        }
 
        #region event
        //构造函数
        public CustomThread()
        {
            // 初始化线程
            _thread = new Thread(Work);
            _thread.IsBackground = true;
            Key = Guid.NewGuid().ToString();
            //线程开始执行
            _thread.Start();
            Console.WriteLine("Thread:" + _thread.ManagedThreadId + " has been created!");
        }
 
        //Set开起信号
        public void Active()
        {
            _locks.Set();
        }
 
        #endregion
    }
    public class CustomFixedThreadPool
    {
        #region Variable
        //创建的线程数
        private int TreadCount = 6;
        //空闲线程队列
        private Queue<CustomThread> _freeThreadQueue;
        //工作线程字典(为什么?)
        private Dictionary<string, CustomThread> _workingDictionary;
        //空闲队列,存放需要被执行的外部函数
        private Queue<WaitCallback> _waitTaskQueue;
 
        #endregion
 
        #region Event
        /// <summary>
        /// 自定义线程池的构造函数
        /// </summary>
        /// <param name="MessageWriteActions">线程输出消息方法列表</param>
        public CustomFixedThreadPool(List<Action<String>> MessageWriteActions)
        {
            _workingDictionary = new Dictionary<string, CustomThread>();
            _freeThreadQueue = new Queue<CustomThread>();
            _waitTaskQueue = new Queue<WaitCallback>();
 
            CustomThread task = null;
            //产生固定数目的线程
            for (int i = 0; i < TreadCount; i++)
            {
                task = new CustomThread();
                //给每一个任务绑定事件
                if (MessageWriteActions.Any())
                {
                    task.MessageWriterAction = MessageWriteActions[i % MessageWriteActions.Count];
                }
                else
                {
                    task.MessageWriterAction = (msg) => { };
                }
                task.WorkCompleted += new Action<CustomThread>(WorkComplete);
                //将每一个新创建的线程放入空闲队列中
                _freeThreadQueue.Enqueue(task);
            }
        }
 
        //线程任务完成之后的工作
        void WorkComplete(CustomThread obj)
        {
            lock (this)
            {
                //将线程从字典中排除
                _workingDictionary.Remove(obj.Key);
                //将该线程放入空闲队列
                _freeThreadQueue.Enqueue(obj);
 
                //判断是否等待队列中有任务未完成
                if (_waitTaskQueue.Count > 0)
                {
                    //取出一个任务
                    WaitCallback item = _waitTaskQueue.Dequeue();
                    CustomThread newTask = null;
                    //空闲队列中取出一个线程
                    newTask = _freeThreadQueue.Dequeue();
                    // 线程执行任务
                    newTask._taskAction = item;
                    //把线程放入到工作队列当中
                    _workingDictionary.Add(newTask.Key, newTask);
                    //设置信号量
                    newTask.Active();
                    return;
                }
                else
                {
                    return;
                }
            }
        }
 
        //添加任务到线程池
        public void AddTaskItem(WaitCallback taskItem)
        {
            lock (this)
            {
                CustomThread task = null;
                //判断空闲队列是否存在线程
                if (_freeThreadQueue.Count > 0)
                {
                    //存在线程,取出一个线程
                    task = _freeThreadQueue.Dequeue();
                    //将该线程放入工作队列
                    _workingDictionary.Add(task.Key, task);
                    //执行传入的任务
                    task._taskAction = taskItem;
                    //设置信号量
                    task.Active();
                    return;
                }
                else
                {
                    //空闲队列中没有空闲线程,就把任务放到等待队列中
                    _waitTaskQueue.Enqueue(taskItem);
                    return;
                }
            }
        }
        #endregion
    }
    
}

  

2.使用方法 (初始化线程池)

 infoLabels = new List<Label>() { this.lbl_info1, this.lbl_info2, this.lbl_info3, this.lbl_info4, this.lbl_info5, this.lbl_info6 };
            List<Action<String>> infoLabelWriters = new List<Action<string>>();
            foreach(Label label in infoLabels)
            {
                infoLabelWriters.Add((msg) => label.CrossThreadRun(()=>label.Text = msg));
            }

            customThreadPool = new CustomFixedThreadPool(infoLabelWriters);

3. 使用方法(完成任务)

复制代码
for(int i = 0; i < 10; i++)
            {
                customThreadPool.AddTaskItem((t) =>
                {
                    var msgWriter = ((CustomThread)t).MessageWriterAction;
                    for(int j = 0; j < 1000; j++)
                    {
                        msgWriter("正在执行第"+(1+j).ToString()+"/1000 条");
                        Thread.Sleep(10);
                    }
                    msgWriter("执行完成!");
                });
            }
复制代码

 或 (增加任务完成标识)

复制代码
            ((Button)sender).Enabled = false;
            int flag = 0;
            for (int i = 0; i < 10; i++)
            {
                customThreadPool.AddTaskItem((t) =>
                {
                    Interlocked.Increment(ref flag);
                    var msgWriter = ((CustomThread)t).MessageWriterAction;
                    for(int j = 0; j < 1000; j++)
                    {
                        msgWriter("正在执行第"+(1+j).ToString()+"/1000 条");
                        Thread.Sleep(10);
                    }
                    msgWriter("执行完成!");
                    Interlocked.Decrement(ref flag);

                    if (flag == 0)
                    {
                        ControlUtil.CrossThreadRun((Button)sender, () => ((Button)sender).Enabled = true);
                    }
                });
            }
复制代码

 

4. 辅助类

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace A9AgentApp.utils
{
   public static class ControlUtil
    {
        /// <summary>
     /// 跨线程访问控件 在控件上执行委托
     /// </summary>
     /// <param name="ctl">控件</param>
     /// <param name="del">执行的委托</param>
        public static void CrossThreadRun(this Control ctl, ThreadStart process)
        {
            if (process == null) return;
            if (ctl.InvokeRequired) { ctl.Invoke(process, null); }
            else
            {
                process();
            }
        }

        /// <summary>
        /// 跨线程访问控件 在控件上执行委托
        /// </summary>
        /// <param name="ctl">控件</param>
        /// <param name="del">执行的委托</param>
        public static Object CrossThreadCall (this Control ctl, Func<Object> func)
        {
            if (ctl.InvokeRequired) {return  ctl.Invoke(func, null); }
            else
            {
               return func();
            }
        }
    }
}
复制代码

 

posted @   zslm___  阅读(470)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
历史上的今天:
2020-11-17 使用Integer存储版本号
2017-11-17 java获取缓存通用类
2016-11-17 通用缓存类
点击右上角即可分享
微信分享提示