我的原創、歡迎轉載、轉載請註明出處、http://www.cnblogs.com/zetee/p/3487084.htmlhtml
多線程這個概念你們都很熟悉,對於winform的開發人員來講.用的仍是多的.但估計都是用Timer,或者backgroundWorker.程序員
你是否曾經想過,寫一個基類,而後....一用到多線程的時候,就立刻能用上呢.編程
沒錯,福利來了,這面我爲你們寫了多線程的一個基類.只有你用到多線程,下面的代碼確定能幫到你不少忙 c#
1 /// <summary> 2 /// 隊列多線程,T 表明處理的單個類型~ 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public abstract class QueueThreadBase<T> 6 { 7 #region 變量&屬性 8 /// <summary> 9 /// 待處理結果 10 /// </summary> 11 private class PendingResult 12 { 13 /// <summary> 14 /// 待處理值 15 /// </summary> 16 public T PendingValue { get; set; } 17 /// <summary> 18 /// 是否有值 19 /// </summary> 20 public bool IsHad { get; set; } 21 } 22 /// <summary> 23 /// 線程數 24 /// </summary> 25 public int ThreadCount 26 { 27 get { return this.m_ThreadCount; } 28 set { this.m_ThreadCount = value; } 29 } 30 private int m_ThreadCount = 5; 31 /// <summary> 32 /// 取消=True 33 /// </summary> 34 public bool Cancel { get; set; } 35 /// <summary> 36 /// 線程列表 37 /// </summary> 38 List<Thread> m_ThreadList; 39 /// <summary> 40 /// 完成隊列個數 41 /// </summary> 42 private volatile int m_CompletedCount = 0; 43 /// <summary> 44 /// 隊列總數 45 /// </summary> 46 private int m_QueueCount = 0; 47 /// <summary> 48 /// 所有完成鎖 49 /// </summary> 50 private object m_AllCompletedLock = new object(); 51 /// <summary> 52 /// 完成的線程數 53 /// </summary> 54 private int m_CompetedCount = 0; 55 /// <summary> 56 /// 隊列鎖 57 /// </summary> 58 private object m_PendingQueueLock = new object(); 59 private Queue<T> m_InnerQueue; 60 #endregion 61 62 63 #region 事件相關 64 /// <summary> 65 /// 所有完成事件 66 /// </summary> 67 public event Action<CompetedEventArgs> AllCompleted; 68 /// <summary> 69 /// 單個完成事件 70 /// </summary> 71 public event Action<T, CompetedEventArgs> OneCompleted; 72 /// <summary> 73 /// 引起所有完成事件 74 /// </summary> 75 /// <param name="args"></param> 76 private void OnAllCompleted(CompetedEventArgs args) 77 { 78 if (AllCompleted != null) 79 { 80 try 81 { 82 AllCompleted(args);//所有完成事件 83 } 84 catch { } 85 } 86 } 87 /// <summary> 88 /// 引起單個完成事件 89 /// </summary> 90 /// <param name="pendingValue"></param> 91 /// <param name="args"></param> 92 private void OnOneCompleted(T pendingValue, CompetedEventArgs args) 93 { 94 if (OneCompleted != null) 95 { 96 try 97 { 98 OneCompleted(pendingValue, args); 99 } 100 catch { } 101 102 } 103 } 104 #endregion 105 106 #region 構造 107 public QueueThreadBase(IEnumerable<T> collection) 108 { 109 m_InnerQueue = new Queue<T>(collection); 110 this.m_QueueCount = m_InnerQueue.Count; 111 } 112 113 #endregion 114 115 #region 主體 116 /// <summary> 117 /// 初始化線程 118 /// </summary> 119 private void InitThread() 120 { 121 m_ThreadList = new List<Thread>(); 122 for (int i = 0; i < ThreadCount; i++) 123 { 124 Thread t = new Thread(new ThreadStart(InnerDoWork)); 125 m_ThreadList.Add(t); 126 t.IsBackground = true; 127 t.Start(); 128 } 129 } 130 /// <summary> 131 /// 開始 132 /// </summary> 133 public void Start() 134 { 135 InitThread(); 136 } 137 /// <summary> 138 /// 線程工做 139 /// </summary> 140 private void InnerDoWork() 141 { 142 try 143 { 144 Exception doWorkEx = null; 145 DoWorkResult doworkResult = DoWorkResult.ContinueThread; 146 var t = CurrentPendingQueue; 147 while (!this.Cancel && t.IsHad) 148 { 149 try 150 { 151 doworkResult = DoWork(t.PendingValue); 152 } 153 catch (Exception ex) 154 { 155 doWorkEx = ex; 156 } 157 m_CompletedCount++; 158 int precent = m_CompletedCount * 100 / m_QueueCount; 159 OnOneCompleted(t.PendingValue, new CompetedEventArgs() { CompetedPrecent = precent, InnerException = doWorkEx }); 160 if (doworkResult == DoWorkResult.AbortAllThread) 161 { 162 this.Cancel = true; 163 break; 164 } 165 else if (doworkResult == DoWorkResult.AbortCurrentThread) 166 { 167 break; 168 } 169 t = CurrentPendingQueue; 170 } 171 172 lock (m_AllCompletedLock) 173 { 174 m_CompetedCount++; 175 if (m_CompetedCount == m_ThreadList.Count) 176 { 177 OnAllCompleted(new CompetedEventArgs() { CompetedPrecent = 100 }); 178 } 179 } 180 181 } 182 catch 183 { 184 throw; 185 } 186 } 187 /// <summary> 188 /// 子類重寫 189 /// </summary> 190 /// <param name="pendingValue"></param> 191 /// <returns></returns> 192 protected virtual DoWorkResult DoWork(T pendingValue) 193 { 194 return DoWorkResult.ContinueThread; 195 } 196 /// <summary> 197 /// 獲取當前結果 198 /// </summary> 199 private PendingResult CurrentPendingQueue 200 { 201 get 202 { 203 lock (m_PendingQueueLock) 204 { 205 PendingResult t = new PendingResult(); 206 if (m_InnerQueue.Count != 0) 207 { 208 t.PendingValue = m_InnerQueue.Dequeue(); 209 t.IsHad = true; 210 } 211 else 212 { 213 t.PendingValue = default(T); 214 t.IsHad = false; 215 } 216 return t; 217 } 218 } 219 } 220 221 #endregion 222 223 #region 相關類&枚舉 224 /// <summary> 225 /// dowork結果枚舉 226 /// </summary> 227 public enum DoWorkResult 228 { 229 /// <summary> 230 /// 繼續運行,默認 231 /// </summary> 232 ContinueThread = 0, 233 /// <summary> 234 /// 終止當前線程 235 /// </summary> 236 AbortCurrentThread = 1, 237 /// <summary> 238 /// 終止所有線程 239 /// </summary> 240 AbortAllThread = 2 241 } 242 /// <summary> 243 /// 完成事件數據 244 /// </summary> 245 public class CompetedEventArgs : EventArgs 246 { 247 public CompetedEventArgs() 248 { 249 250 } 251 /// <summary> 252 /// 完成百分率 253 /// </summary> 254 public int CompetedPrecent { get; set; } 255 /// <summary> 256 /// 異常信息 257 /// </summary> 258 public Exception InnerException { get; set; } 259 } 260 #endregion 261 262 }
1.從構造函數來看,處理的是一個肯定的列表.沒錯.這個多線程只能處理已經肯定的列表,你是否會問.可不能夠一邊添加,一邊處理呢?(呵呵,能夠,請聯繫樓主,固然你也能夠本身寫,是吧?!)多線程
public QueueThreadBase(IEnumerable<T> collection)
2.提供撤銷的功能ide
/// <summary> /// 取消=True /// </summary> public bool Cancel { get; set; }
3.提供線程個數修改功能函數
/// <summary> /// 線程數 /// </summary> public int ThreadCount { get { return this.m_ThreadCount; } set { this.m_ThreadCount = value; } }
4.提供多種事件響應,如單個完成,所有完成的事件學習
/// <summary> /// 所有完成事件 /// </summary> public event Action<CompetedEventArgs> AllCompleted; /// <summary> /// 單個完成事件 /// </summary> public event Action<T, CompetedEventArgs> OneCompleted;
5.提供完成的百分率this
/// <summary> /// 完成事件數據 /// </summary> public class CompetedEventArgs : EventArgs { public CompetedEventArgs() { } /// <summary> /// 完成百分率 /// </summary> public int CompetedPrecent { get; set; } /// <summary> /// 異常信息 /// </summary> public Exception InnerException { get; set; } }
6.提供終止線程的方式,繼續/單線程終止/所有終止spa
/// <summary> /// dowork結果枚舉 /// </summary> public enum DoWorkResult { /// <summary> /// 繼續運行,默認 /// </summary> ContinueThread = 0, /// <summary> /// 終止當前線程 /// </summary> AbortCurrentThread = 1, /// <summary> /// 終止所有線程 /// </summary> AbortAllThread = 2 }
你是否會問?怎麼用呢?別急....請看
1 /// <summary> 2 /// 下載線程對了. 3 /// </summary> 4 public class DownLoadQueueThread:QueueThreadBase<int> 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 /// <param name="list">下載的列表ID</param> 10 public DownLoadQueueThread(IEnumerable<int> list):base(list) 11 { 12 13 } 14 /// <summary> 15 /// 每次多線程都到這裏來,處理多線程 16 /// </summary> 17 /// <param name="pendingValue"列表ID></param> 18 /// <returns></returns> 19 protected override DoWorkResult DoWork(int pendingID) 20 { 21 try 22 { 23 24 //..........多線程處理.... 25 return DoWorkResult.ContinueThread;//沒有異常讓線程繼續跑.. 26 27 } 28 catch (Exception) 29 { 30 31 return DoWorkResult.AbortCurrentThread;//有異常,能夠終止當前線程.固然.也能夠繼續, 32 //return DoWorkResult.AbortAllThread; //特殊狀況下 ,有異常終止全部的線程... 33 } 34 35 //return base.DoWork(pendingValue); 36 } 37 }
總結:
多線程在何時都會用到.不用到是你不會用.多線程要必定的編程基礎,若是你以爲有點難度,那你能夠學習而且借鑑人家已有的東西.少走彎路,是咱們程序員經歷嗷嗷待哺後的心聲.本文以交流態度和感恩心態,貢獻給有須要的人們.