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(); } } } }