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

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 @ 2022-11-17 11:36  zslm___  阅读(391)  评论(0编辑  收藏  举报