Fork me on GitHub
c#通用多线程基类,以队列形式

 

个人原创、欢迎转载、转载请注明出处、http://www.cnblogs.com/zetee/p/3487084.html

  多线程这个概念大家都很熟悉,对于winform的开发人员来说.用的还是多的.但估计都是用Timer,或者backgroundWorker.

  你是否曾经想过,写一个基类,然后....一用到多线程的时候,就马上能用上呢.

没错,福利来了,这面我为大家写了多线程的一个基类.只有你用到多线程,下面的代码肯定能帮到你很多忙 

复制代码
  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.提供撤销的功能

     /// <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.提供完成的百分率

复制代码
        /// <summary>
        /// 完成事件数据
        /// </summary>
        public class CompetedEventArgs : EventArgs
        {
            public CompetedEventArgs()
            {

            }
            /// <summary>
            /// 完成百分率
            /// </summary>
            public int CompetedPrecent { get; set; }
            /// <summary>
            /// 异常信息
            /// </summary>
            public Exception InnerException { get; set; }
        } 
复制代码

  6.提供终止线程的方式,继续/单线程终止/全部终止

复制代码
        /// <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     }
复制代码

 

  总结:

  多线程在什么时候都会用到.不用到是你不会用.多线程要一定的编程基础,如果你觉得有点难度,那你可以学习并且借鉴人家已有的东西.少走弯路,是我们程序员经历嗷嗷待哺后的心声.本文以交流态度和感恩心态,贡献给有需要的人们.

 
 
 
标签: 多线程.net
 
posted on 2013-12-24 18:35  HackerVirus  阅读(241)  评论(0编辑  收藏  举报