代码改变世界

多线程通用处理队列类(二)

2017-11-02 12:06  Dorisoy  阅读(415)  评论(0编辑  收藏  举报
  1     public class DownLoadFile
  2     {
  3         public string FileName { get; set; }
  4 
  5     }
  6     /// <summary>
  7     /// 下载线程队列
  8     /// </summary>
  9     public class DownLoadQueueThread : QueueThreadBase<DownLoadFile>
 10     {
 11         /// <summary>
 12         /// 
 13         /// </summary>
 14         /// <param name="list">下载的列表ID</param>
 15         public DownLoadQueueThread(IEnumerable<DownLoadFile> list)
 16             : base(list)
 17         {
 18 
 19         }
 20         /// <summary>
 21         /// 每次多线程都到这里来,处理多线程
 22         /// </summary>
 23         /// <param name="pendingValue"列表ID></param>
 24         /// <returns></returns>
 25         protected override DoWorkResult DoWork(DownLoadFile pendingFile)
 26         {
 27             try
 28             {
 29                 //Thread.Sleep(5000);
 30                 for (int i = 0; i < 100000; i++)
 31                 {
 32                     //Thread.Sleep(100);
 33                 }
 34                 //..........多线程处理....
 35                 return DoWorkResult.ContinueThread;//没有异常让线程继续跑..
 36             }
 37             catch (Exception)
 38             {
 39                 return DoWorkResult.AbortCurrentThread;//有异常,可以终止当前线程.当然.也可以继续,
 40                 //return  DoWorkResult.AbortAllThread; //特殊情况下 ,有异常终止所有的线程...
 41             }
 42 
 43             //return base.DoWork(pendingValue);
 44         }
 45     }
 46 
 47     /// <summary>
 48     /// 队列多线程,T 代表处理的单个类型~
 49     /// </summary>
 50     /// <typeparam name="T"></typeparam>
 51     public abstract class QueueThreadBase<T>
 52     {
 53         #region 变量&属性
 54         /// <summary>
 55         /// 待处理结果
 56         /// </summary>
 57         private class PendingResult
 58         {
 59             /// <summary>
 60             /// 待处理值
 61             /// </summary>
 62             public T PendingValue { get; set; }
 63             /// <summary>
 64             /// 是否有值
 65             /// </summary>
 66             public bool IsHad { get; set; }
 67         }
 68         /// <summary>
 69         /// 线程数
 70         /// </summary>
 71         public int ThreadCount
 72         {
 73             get { return this.m_ThreadCount; }
 74             set { this.m_ThreadCount = value; }
 75         }
 76         private int m_ThreadCount = 5;
 77         /// <summary>
 78         /// 取消=True
 79         /// </summary>
 80         public bool Cancel { get; set; }
 81         /// <summary>
 82         /// 线程列表
 83         /// </summary>
 84         List<Thread> m_ThreadList;
 85         /// <summary>
 86         /// 完成队列个数
 87         /// </summary>
 88         private volatile int m_CompletedCount = 0;
 89         /// <summary>
 90         /// 队列总数
 91         /// </summary>
 92         private int m_QueueCount = 0;
 93         /// <summary>
 94         /// 全部完成锁
 95         /// </summary>
 96         private object m_AllCompletedLock = new object();
 97         /// <summary>
 98         /// 完成的线程数
 99         /// </summary>
100         private int m_CompetedCount = 0;
101         /// <summary>
102         /// 队列锁
103         /// </summary>
104         private object m_PendingQueueLock = new object();
105         private Queue<T> m_InnerQueue;
106         #endregion
107 
108         #region 事件相关
109         /// <summary>
110         /// 全部完成事件
111         /// </summary>
112         public event Action<CompetedEventArgs> AllCompleted;
113         /// <summary>
114         /// 单个完成事件
115         /// </summary>
116         public event Action<T, CompetedEventArgs> OneCompleted;
117         /// <summary>
118         /// 引发全部完成事件
119         /// </summary>
120         /// <param name="args"></param>
121         private void OnAllCompleted(CompetedEventArgs args)
122         {
123             if (AllCompleted != null)
124             {
125                 try
126                 {
127                     AllCompleted(args);//全部完成事件
128                 }
129                 catch { }
130             }
131         }
132         /// <summary>
133         /// 引发单个完成事件
134         /// </summary>
135         /// <param name="pendingValue"></param>
136         /// <param name="args"></param>
137         private void OnOneCompleted(T pendingValue, CompetedEventArgs args)
138         {
139             if (OneCompleted != null)
140             {
141                 try
142                 {
143                     OneCompleted(pendingValue, args);
144                 }
145                 catch { }
146 
147             }
148         }
149         #endregion
150 
151         #region 构造
152         public QueueThreadBase(IEnumerable<T> collection)
153         {
154             m_InnerQueue = new Queue<T>(collection);
155             this.m_QueueCount = m_InnerQueue.Count;
156         }
157 
158         #endregion
159 
160         #region 主体
161         /// <summary>
162         /// 初始化线程
163         /// </summary>
164         private void InitThread()
165         {
166             m_ThreadList = new List<Thread>();
167             for (int i = 0; i < ThreadCount; i++)
168             {
169                 Thread t = new Thread(new ThreadStart(InnerDoWork));
170                 m_ThreadList.Add(t);
171                 t.IsBackground = true;
172                 t.Start();
173             }
174         }
175         /// <summary>
176         /// 开始
177         /// </summary>
178         public void Start()
179         {
180             InitThread();
181         }
182         /// <summary>
183         /// 线程工作
184         /// </summary>
185         private void InnerDoWork()
186         {
187             try
188             {
189                 Exception doWorkEx = null;
190                 DoWorkResult doworkResult = DoWorkResult.ContinueThread;
191                 var t = CurrentPendingQueue;
192                 while (!this.Cancel && t.IsHad)
193                 {
194                     try
195                     {
196                         doworkResult = DoWork(t.PendingValue);
197                     }
198                     catch (Exception ex)
199                     {
200                         doWorkEx = ex;
201                     }
202                     m_CompletedCount++;
203                     int precent = m_CompletedCount * 100 / m_QueueCount;
204                     OnOneCompleted(t.PendingValue, new CompetedEventArgs() { CompetedPrecent = precent, InnerException = doWorkEx });
205                     if (doworkResult == DoWorkResult.AbortAllThread)
206                     {
207                         this.Cancel = true;
208                         break;
209                     }
210                     else if (doworkResult == DoWorkResult.AbortCurrentThread)
211                     {
212                         break;
213                     }
214                     t = CurrentPendingQueue;
215                 }
216 
217                 lock (m_AllCompletedLock)
218                 {
219                     m_CompetedCount++;
220                     if (m_CompetedCount == m_ThreadList.Count)
221                     {
222                         OnAllCompleted(new CompetedEventArgs() { CompetedPrecent = 100 });
223                     }
224                 }
225 
226             }
227             catch
228             {
229                 throw;
230             }
231         }
232         /// <summary>
233         /// 子类重写
234         /// </summary>
235         /// <param name="pendingValue"></param>
236         /// <returns></returns>
237         protected virtual DoWorkResult DoWork(T pendingValue)
238         {
239             return DoWorkResult.ContinueThread;
240         }
241         /// <summary>
242         /// 获取当前结果
243         /// </summary>
244         private PendingResult CurrentPendingQueue
245         {
246             get
247             {
248                 lock (m_PendingQueueLock)
249                 {
250                     PendingResult t = new PendingResult();
251                     if (m_InnerQueue.Count != 0)
252                     {
253                         t.PendingValue = m_InnerQueue.Dequeue();
254                         t.IsHad = true;
255                     }
256                     else
257                     {
258                         t.PendingValue = default(T);
259                         t.IsHad = false;
260                     }
261                     return t;
262                 }
263             }
264         }
265 
266         #endregion
267 
268         #region 相关类&枚举
269         /// <summary>
270         /// dowork结果枚举
271         /// </summary>
272         public enum DoWorkResult
273         {
274             /// <summary>
275             /// 继续运行,默认
276             /// </summary>
277             ContinueThread = 0,
278             /// <summary>
279             /// 终止当前线程
280             /// </summary>
281             AbortCurrentThread = 1,
282             /// <summary>
283             /// 终止全部线程
284             /// </summary>
285             AbortAllThread = 2
286         }
287         /// <summary>
288         /// 完成事件数据
289         /// </summary>
290         public class CompetedEventArgs : EventArgs
291         {
292             public CompetedEventArgs()
293             {
294 
295             }
296             /// <summary>
297             /// 完成百分率
298             /// </summary>
299             public int CompetedPrecent { get; set; }
300             /// <summary>
301             /// 异常信息
302             /// </summary>
303             public Exception InnerException { get; set; }
304         }
305         #endregion
306 
307     }