首页 新闻 搜索 专区 学院

请教一下,asp.net如何创建一个模拟线程池

0
悬赏园豆:10 [待解决问题]

  之前参照某位高手的代码(忘了是哪一位了,不好意思),试着到.net去模拟一个任务线程池.

主要的思路如下:

1、创建一个单例对象,这个单例对象上面有两个字典变量,两个队列变量,分别保存所有线程的引用, 工作队列,还有正在执行的线程队列,空闲的线程队列.

2、在这个单例对象里,还设一个主线程,以一定时间轮询更新以上四个变量的信息。

3、线程的主要任务是执行相关sql语句,执行完后,或生成文件,或执行任务脚本程序,有点类型oracle的job,但是比它更灵活一点。

以上是代码片断

 

  1  public class TaskJobPool : IDisposable
  2     {
  3      
  4          public  Dictionary<int, JobEntity> poolDic; //所有的线程池线的所有线程
  5          public   Queue<TaskInst> jobQueue;                   //待执行的任务队列
  6          public   Dictionary<int, JobEntity> workJobQueue;      //正在工作队列
  7          public   Queue<JobEntity> freeQueue;                    //空闲队列
  8 
  9 
 10         int minPoolSize = 10; //最小线程数
 11         int maxPoolSize = 50;//最大线程数
 12         int incrementPoolSize = 5; //当活动线程不足的时候新增线程的增量
 13 
 14         //设置最大线程数
 15 
 16         public   void  SetMaxSize(int Value)
 17         {
 18             lock (this)
 19             {
 20                 maxPoolSize = Value;
 21             }
 22 
 23         }
 24 
 25         //设置最小线程数
 26         public   void SetMinSize(int Value)
 27         {
 28             lock (this)
 29             {
 30                 minPoolSize = Value;
 31             }
 32 
 33         }
 34 
 35         //设置增量
 36         public   void SetIncrement(int Value)
 37         {
 38             lock (this)
 39             {
 40                 incrementPoolSize = Value;
 41             }
 42 
 43         }
 44 
 45         private TaskJobPool()
 46         {
 47             //
 48             //TODO: 在此处添加构造函数逻辑
 49             //
 50             poolDic = new Dictionary<int, JobEntity>();
 51             jobQueue = new Queue<TaskInst>();
 52             workJobQueue = new Dictionary<int, JobEntity>();
 53             freeQueue = new Queue<JobEntity>();
 54 
 55  
 56             
 57         }
 58 
 59 
 60         //任务队列
 61        private static TaskJobPool _TaskJobPool = null;
 62        private static readonly object padlock = new object();
 63 
 64         public static TaskJobPool GetInstance()
 65         {
 66             if (_TaskJobPool == null)
 67             {
 68                 lock (padlock)
 69                 {
 70 
 71 
 72                     _TaskJobPool = (TaskJobPool)WebCache.GetWebCache().GetApplicationCache("TaskJobPool");
 73                   
 74 
 75                 
 76 
 77 
 78                     if (_TaskJobPool == null)
 79                     {
 80                         _TaskJobPool = new TaskJobPool();
 81                         WebCache.GetWebCache().SetApplicationCache("TaskJobPool", _TaskJobPool);
 82                      
 83                     }
 84                 }
 85             } 
 86             return _TaskJobPool;
 87            
 88         }
 89 
 90         //线程执行完毕后的触发事件  (相当于旧线程池的轮询主方法)
 91 
 92 
 93         public void ReStartService()
 94         {
 95             try
 96             {
 97                 Dispose();
 98 
 99                 poolDic.Clear();
100                 workJobQueue.Clear();
101                 jobQueue.Clear();
102                 freeQueue.Clear();
103 
104                 if (mainThread != null)
105                 {
106                     Thread th = mainThread;
107                     th.Abort();
108                     mainThread = null;
109                 }
110                 StartService();
111             }
112             catch (Exception e)
113             {
114             }
115             
116         }
117 
118         public void StartService()
119         {
120             try
121             {
122                 JobEntity je = null;
123                 //先创建最小线程数的线程
124 
125                 if (poolDic.Count == 0)
126                 {
127                     for (int i = 0; i < minPoolSize; i++)
128                     {
129                         if (poolDic.ContainsKey(i + 1)) break;
130                         je = new JobEntity();
131                         je.Key = i + 1;
132                         //注册线程完成时触发的事件
133                         je.WorkComplete += new Action<JobEntity>(j_WorkComplete);
134                         //加入到所有线程的字典中
135                         poolDic.Add(i + 1, je);
136                         //因为还没加入具体的工作委托就先放入空闲队列
137                         freeQueue.Enqueue(je);
138 
139                         
140                     }
141                 }
142 
143                 Refresh();
144                 StartTask();
145 
146 
147                 if (!TaskJobPool.getThread().IsAlive)
148                     TaskJobPool.getThread().Start();
149             }
150             catch (Exception e) { }
151            
152         }
153 
154 
155         static Thread mainThread = null;
156         public static Thread getThread()
157         {
158             try
159             {
160                 if (mainThread == null)
161                 {
162                     mainThread = new Thread(new ThreadStart(TaskJobPool.GetInstance().MasterScanMethod));
163                     mainThread.IsBackground = true;
164                 }
165 
166                
167             }
168             catch (Exception e) { }
169             return mainThread;
170         }
171 
172 
173         public void MasterScanMethod()
174         {
175             
176                 while (  true)
177                 {
178                     Refresh();
179                     StartTask();
180                     Thread.Sleep(300000);
181                 }
182 
183                 //删除过期的表
184                 TaskInstTableImp titi = new TaskInstTableImp(0, "gsm");
185                 titi.DeleteTaskTempTable(0);
186             
187         }
188 
189 
190         public void StopService()
191         {
192            
193                 foreach (JobEntity j in poolDic.Values)
194                 {
195 
196                     //关闭所有的线程
197                     //using (j) { j.Close(); }
198                     j.Close();
199 
200                 }
201 
202 
203                 if (mainThread != null)
204                 {
205                     Thread th = mainThread;
206                     th.Abort();
207                     mainThread = null;
208                 }
209  
210         }
211 
212 
213         public void Refresh() //刷新任务单数据
214         {
215            
216                 lock (new object())
217                 {
218                     //刷新任务队列清单
219                     TaskInstImp task_inst_imp = new TaskInstImp(0, "gsm");
220                     IList<TaskInst> tasks = task_inst_imp.GetExecTartgetTask();
221                     foreach (TaskInst entity in tasks)
222                     {
223                         if (jobQueue.Where<TaskInst>(p => p.Id == entity.Id).ToList<TaskInst>().Count == 0) //如果作务队列有的,就不加进去
224                             jobQueue.Enqueue(entity);
225                     }
226 
227                 }
228           
229      }
230 
231 
232         public void StartTask()  //启动任务单
233         {
234              
235 
236                 TaskInstImp task_inst_imp = new TaskInstImp(0, "gsm");
237              
238 
239                 lock (typeof(TaskJobPool))
240                 {
241                     while (jobQueue.Count > 0)  //如果有待处理的任务单
242                     {
243                         //出列
244                         TaskInst task = jobQueue.Dequeue();
245                         JobEntity je = null;
246                         if (freeQueue.Count > 0) //存在空闲线程
247                         {
248                             je = freeQueue.Dequeue();
249                         }
250                         else     //不存在空闲线程就新增一个
251                         {
252                             if (poolDic.Count >= minPoolSize && poolDic.Count < maxPoolSize)
253                             {
254 
255                                 je = new JobEntity();
256 
257                                 //job ID号拾漏
258                                 for (int freeI = 1; freeI < maxPoolSize; freeI++)
259                                 {
260                                     if (!poolDic.ContainsKey(freeI))
261                                     {
262                                         je.Key = freeI;
263                                         break;
264                                     }
265 
266                                 }
267                                 //je.Key = i + 1;
268                                 //注册线程完成时触发的事件
269                                 je.WorkComplete += new Action<JobEntity>(j_WorkComplete);
270                                 //加入到所有线程的字典中
271                                 poolDic.Add(je.Key, je);
272                                
273                             }
274                             else
275                                 break;
276                         }
277 
278                         je.contextdata = task.Id;
279                         //任务状态置一下,否则会被重复执行
280                         TaskInst task_inst = task_inst_imp.Load(task.Id);
281                         task_inst.State = "A";
282                         task_inst.UpdateDate = DateTime.Now;
283                         task_inst_imp.Update(task_inst);
284 
285 
286 
287                         workJobQueue.Add(je.Key, je);
288                         //唤醒线程开始执行
289                         je.Active();
290 
291 
292 
293                     }
294 
295 
296                     
297                     Queue<JobEntity> t = new Queue<JobEntity>();
298                     while (freeQueue.Count > 0)
299                     {
300 
301                         JobEntity tt = freeQueue.Dequeue();
302 
303                         if (tt.Key > minPoolSize)
304                         {
305                             tt.contextdata = null;
306                             poolDic.Remove(tt.Key);
307                             tt.Dispose();
308                         }
309                         else
310                             t.Enqueue(tt);
311                     }
312 
313                     while (t.Count > 0)
314                     {
315                         freeQueue.Enqueue(t.Dequeue());
316                     }
317 
318 
319 
320                 }
321                 foreach (JobEntity j in workJobQueue.Values.ToList<JobEntity>().Where<JobEntity>(p => !p.Working).ToList<JobEntity>())
322                 {
323                      
324                     j.Active();
325                    
326                 }
327              
328         }
329 
330  
331         void j_WorkComplete(JobEntity obj)
332         {
333            
334                 lock (this)
335                 {
336                     //本线程执行完毕,需要从工作字典集合中剔除
337                     workJobQueue.Remove(obj.Key);
338                     //线程关闭
339                     obj.Close();
340                     ////线程池状态更新
341                     //poolDic.Remove(obj.Key);
342                     //poolDic.Add(obj.Key, obj);
343 
344 
345                     //刷新工单池信息
346                     Refresh();
347 
348                     //当任务队列没有单时,就将额外增加的线程注销掉,以减轻系统负载
349                     //if (jobQueue.Count == 0 && freeQueue.Count > minPoolSize)
350                     //{
351                     //线程标识大于最小线程数时,注销
352                     if (jobQueue.Count == 0 && obj.Key > minPoolSize)
353                     {
354                         poolDic.Remove(obj.Key);
355                         obj.contextdata = null;
356                         obj.Dispose();
357                     }
358                     else
359                     {
360                         //  如果线程标识没有超过最小线程数就把线程从工作字典放入空闲队列
361                         obj.contextdata = null;
362                         freeQueue.Enqueue(obj);
363                     }
364                     //}
365 
366                     StartTask();
367 
368 
369                 }
370           
371         }
372      public void Dispose()
373         {
374          
375                 foreach (JobEntity j in poolDic.Values)
376                 {
377 
378                     //关闭所有的线程
379 
380                     //using (j) { j.Dispose(); }
381                     j.Dispose();
382 
383                 }
384             
385                 poolDic.Clear();
386                 workJobQueue.Clear();
387                 jobQueue.Clear();
388                 freeQueue.Clear();
389 
390                 if (mainThread != null)
391                 {
392                     Thread th = mainThread;
393                     th.Abort();
394                     mainThread = null;
395                 }
396        
397            
398         }
399  
400     }

 

    现在有个问题:这个线程池,在小任务执行,还可以多线程同时执行,但是时间一长,如三小时后,上面的四个变量变为空,了也就是说:差不多一定时间表后,似乎.net会回收资源,造成相信关变量被初始化,为啥会出现这种情况, 烦请大虾指教.

 

快乐是短暂的的主页 快乐是短暂的 | 初学一级 | 园豆:6
提问于:2014-03-25 18:22
< >
分享
所有回答(1)
1

话说能不能给线程赋一个方法让他去执行?而不是新建线程的时候指定方法?

至于资源回收,那是iis的应用程序池回收机制.你可以把他关了.默认是20分钟没有请求就会回收应用程序池

吴瑞祥 | 园豆:29369 (高人七级) | 2014-03-25 19:15

线程赋予一个方法?能否具体举例?

另外,如果把iis的应用程序池回收机制关了,那么正常的请求那不是不会正常回收了,那么时候系统资源会不会用尽?

支持(0) 反对(0) 快乐是短暂的 | 园豆:6 (初学一级) | 2014-03-27 00:28

@快乐是短暂的: 不然你的线程池是怎么实现线程重用的,就是一个线程执行完毕后,你怎么让他重新打开?

ASP.NET是有GC的,要是因为把IIS回收关了系统资源就用尽了.那说明你的代码有问题

支持(0) 反对(0) 吴瑞祥 | 园豆:29369 (高人七级) | 2014-03-27 09:01

@吴瑞祥:  

1、一个线程执行完毕后,通过线程锁暂停。实际上,我线程执行方法是固定的,变化的只是传入的作业标识。只不过线程执行完成后,需要对对应的连接池进行清理。

2、ASP.NET是有GC的,要是因为把IIS回收关了系统资源就用尽了.那说明你的代码有问题

----在外面有写一个定时刷新网页的方式,会自动重启iis进程,任务退出也有记录断点,重启后会继续执行

支持(0) 反对(0) 快乐是短暂的 | 园豆:6 (初学一级) | 2014-07-07 13:54
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册