可控Threadpool设计

来源:互联网 发布:mac连接wifi但不能上网 编辑:程序博客网 时间:2024/06/07 03:07

AbortableThreadPool
可控Threadpool设计


我们在使用.net类库自带的threadpool的时候,很方便,但有时也会发现存在一些问题。
比如加入的任务不好控制,如果我想中止正在执行的任务,或者如果想等待threadpool 中的任务执行完成,程序再退出.基于这个问题,写了一个AbortableThreadPool类,实际项目中可以直接拿来用.
AbortableThreadPool.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;


namespace Debug
{
   //任务 状态
   public enum WorkItemStatus
   {
     Completed,  //完成
     Queued,    //入队
     Executing,  //执行
     Aborted    //中止
   }
   //任务
   public sealed class WorkItem
   {
     private WaitCallback callback;  //Thread pool 的回调代理
     private object state;        //回调参数
     private ExecutionContext ctx;   //与执行的逻辑线程相关的所有信息上下文

     internal WorkItem(WaitCallback callback, object state, ExecutionContext ctx)
     {
        this.callback = callback;
        this.state = state;
        this.ctx = ctx;
     }

     internal WaitCallback Callback
     {
        get
        {
           return callback;
        }
     }

     internal object State
     {
        get
        {
           return state;
        }
     }

     internal ExecutionContext Context
     {
        get
        {
           return ctx;
        }
     }
   }

   //可终止线程池
   public class AbortableThreadPool
   {
     private LinkedList<WorkItem> callbacks = new LinkedList<WorkItem>();             //任务列表
     private Dictionary<WorkItem, Thread> threads = new Dictionary<WorkItem, Thread>(); //线程列表

     //加入任务对列
     public WorkItem QueueUserWorkItem(WaitCallback callback)
     {
        return QueueUserWorkItem(callback, null);
     }
     public WorkItem QueueUserWorkItem(WaitCallback callback, object state)
     {
        if (callback == null) throw new ArgumentNullException("callback");


        WorkItem item = new WorkItem(callback, state, ExecutionContext.Capture());
        lock (callbacks)
        {
           callbacks.AddLast(item);
        }
        ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem));
        return item;
     }

     private void HandleItem(object ignored)
     {
        WorkItem item = null;
        try
        {
           lock (callbacks)
           {
               if (callbacks.Count > 0)
               {
                  item = callbacks.First.Value;
                  callbacks.RemoveFirst();
               }
               if (item == null)
                  return;
               threads.Add(item, Thread.CurrentThread);
           }
           ExecutionContext.Run(item.Context,
               delegate { item.Callback(item.State); }, null);
        }
        finally
        {
           lock (callbacks)
           {
               if (item != null)
                  threads.Remove(item);
           }
        }
     }
     //是否是可中止线程
     public bool IsAbortableThread(Thread thread)
     {
        lock (callbacks)
        {
           foreach (Thread t in threads.Values)
           {
               if (t == thread)
                  return true;
           }
           return false;
        }
     }
     //取消任务
     public WorkItemStatus Cancel(WorkItem item, bool allowAbort)
     {
        if (item == null)
           throw new ArgumentNullException("item");
        lock (callbacks)
        {
           LinkedListNode<WorkItem> node = callbacks.Find(item);
           if (node != null)
           {
               callbacks.Remove(node);
               return WorkItemStatus.Queued;
           }
           else if (threads.ContainsKey(item))
           {
               if (allowAbort)
               {
                  threads[item].Abort();
                  threads.Remove(item);
                  return WorkItemStatus.Aborted;
               }
               else
                  return WorkItemStatus.Executing;
           }
           else
               return WorkItemStatus.Completed;
        }
     }
     //取消所有任务
     public void CancelAll(bool allowAbort)
     {
        lock (callbacks)
        {
           callbacks.Clear();
           if (allowAbort)
           {
               foreach (Thread t in threads.Values)
                  t.Abort();
           }
        }
     }
     //排队任务数
     public int QueueCount
     {
        get { return callbacks.Count; }
     }
     //工作任务数
     public int WorkingCount
     {
        get { return threads.Count; }
     }
     //类似Thread.Join,等待AbortableThreadPool执行完成
     public void Join()
     {
        foreach (Thread thread in threads.Values.ToArray())
        {
           thread.Join();
        }
     }

     public bool Join(int millisecondsTimeout)
     {
        foreach (Thread thread in threads.Values.ToArray())
        {
           if (!thread.Join(millisecondsTimeout))
               return false;
        }
        return true;
     }

     public bool Join(TimeSpan timeout)
     {
        foreach (Thread thread in threads.Values.ToArray())
        {
           if (!thread.Join(timeout))
               return false;
        }
        return true;
     }
   }
}

Debug.cs 测试代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Debug
{
   class Program
   {
     static void Main(string[] args)
     {
        AbortableThreadPool abortableThreadPool = new AbortableThreadPool();
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}",abortableThreadPool.QueueCount,abortableThreadPool.WorkingCount));
        WorkItem workItem1 = abortableThreadPool.QueueUserWorkItem(new WaitCallback(Test));
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}",abortableThreadPool.QueueCount,abortableThreadPool.WorkingCount));
        WorkItem workItem2 = abortableThreadPool.QueueUserWorkItem(new WaitCallback(Test));
        WorkItem workItem3 = abortableThreadPool.QueueUserWorkItem(new WaitCallback(Test));
        WorkItem workItem4 = abortableThreadPool.QueueUserWorkItem(new WaitCallback(Test));
        WorkItem workItem5 = abortableThreadPool.QueueUserWorkItem(new WaitCallback(Test));
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}",abortableThreadPool.QueueCount,abortableThreadPool.WorkingCount));
        Thread.Sleep(1000);
        Console.WriteLine(abortableThreadPool.Cancel(workItem1, false));
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}",abortableThreadPool.QueueCount,abortableThreadPool.WorkingCount));
        Thread.Sleep(1000);
        Console.WriteLine(abortableThreadPool.Cancel(workItem1, true));
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}",abortableThreadPool.QueueCount,abortableThreadPool.WorkingCount));
        Thread.Sleep(1000);
        abortableThreadPool.CancelAll(true);
        abortableThreadPool.Join(); //等待所有任务退出
        Console.WriteLine(string.Format("QueueCount:{0},WorkingCount:{1}", abortableThreadPool.QueueCount, abortableThreadPool.WorkingCount));
     }
     static void Test(object state)
     {
        int i = 1000;
        while (i-- > 0)
        {
           Console.WriteLine(i);
           Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(800));
        }
     }
   }
}

测试输出:
QueueCount:0,WorkingCount:0
QueueCount:1,WorkingCount:0
QueueCount:5,WorkingCount:0
999
999
998
998
997
997
Executing
QueueCount:2,WorkingCount:3
999
996
996
995
995
994
994
999
998
997
996
Aborted
QueueCount:0,WorkingCount:4
999
993
995
998
997
998
992
994
QueueCount:0,WorkingCount:0
Press any key to continue . . .

原创粉丝点击