一个C#多线程的工作队列 ,c# 多线程排队队列实现的源码

http://blog.csdn.net/loveandangle/article/details/6733642

自己写了一个多线程的工作队列,能够实现对队列中对象的自动处理。多线程添加元素到队列中,队列根据绑定

的事件进行自动处理,可以设置WorkSequential属性来实现对队列处理的单线程(严格顺序处理)或者多线程处理(循序出队,但是

多线程处理,不保证对队列元素的处理顺利)的选择。

 

  源码:

 

代码
复制代码
   
   
/* **********多线程的工作队列*************** * 此工作队列保证线程安全性 * * * * * ****** */ namespace WorkQueue { using System.Collections.Generic; using System; using System.Threading; public delegate void UserWorkEventHandler < T > ( object sender, WorkQueue < T > .EnqueueEventArgs e); public class WorkQueue < T > { private bool IsWorking; // 表明处理线程是否正在工作 private object lockIsWorking = new object (); // 对IsWorking的同步对象 private Queue < T > queue; // 实际的队列 private object lockObj = new object (); // 队列同步对象 /// <summary> /// 绑定用户需要对队列中的item对象 /// 施加的操作的事件 /// </summary> public event UserWorkEventHandler < T > UserWork; public WorkQueue( int n) { queue = new Queue < T > (n); } public WorkQueue() { queue = new Queue < T > (); } /// <summary> /// 谨慎使用此函数, /// 只保证此瞬间,队列值为空 /// </summary> /// <returns></returns> public bool IsEmpty() { lock (lockObj) { return queue.Count == 0 ; } } private bool isOneThread; /// <summary> /// 队列处理是否需要单线程顺序执行 /// ture表示单线程处理队列的T对象 /// 默认为false,表明按照顺序出队,但是多线程处理item /// *****注意不要频繁改变此项**** /// </summary> public bool WorkSequential { get { return isOneThread; } set { isOneThread = value; } } /// <summary> /// 向工作队列添加对象, /// 对象添加以后,如果已经绑定工作的事件 /// 会触发事件处理程序,对item对象进行处理 /// </summary> /// <param name="item"> 添加到队列的对象 </param> public void EnqueueItem(T item) { lock (lockObj) { queue.Enqueue(item); } lock (lockIsWorking) { if ( ! IsWorking) { IsWorking = true ; ThreadPool.QueueUserWorkItem(doUserWork); } } } /// <summary> /// 处理队列中对象的函数 /// </summary> /// <param name="o"></param> private void doUserWork( object o) { try { T item; while ( true ) { lock (lockObj) { if (queue.Count > 0 ) { item = queue.Dequeue(); } else { return ; } } if ( ! item.Equals( default (T))) { if (isOneThread) { if (UserWork != null ) { UserWork( this , new EnqueueEventArgs(item)); } } else { ThreadPool.QueueUserWorkItem(obj => { if (UserWork != null ) { UserWork( this , new EnqueueEventArgs(obj)); } }, item); } } } } finally { lock (lockIsWorking) { IsWorking = false ; } } } /// <summary> /// UserWork事件的参数,包含item对象 /// </summary> public class EnqueueEventArgs : EventArgs { public T Item { get ; private set ; } public EnqueueEventArgs( object item) { try { Item = (T)item; } catch (Exception) { throw new InvalidCastException( " object to T 转换失败 " ); } } } } }
复制代码

 

 

 

 

  示例代码:
代码
复制代码
    
    
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.IO; using WorkQueue; namespace Program { class Program { private static List < string > list = new List < string > ( 1000 ); static StreamWriter sw = new StreamWriter( new FileStream( " test.dat " , FileMode.Create)); static void Main( string [] args) { WorkQueue < int > workQueue = new WorkQueue < int > ( 1000 ); workQueue.UserWork += new UserWorkEventHandler < int > (workQueue_UserWork); // workQueue.WorkSequential = true; ThreadPool.QueueUserWorkItem(o => { for ( int i = 0 ; i < 1000 ; i ++ ) { workQueue.EnqueueItem(i); } }); Console.ReadLine(); list.ForEach(str => sw.WriteLine(str)); Console.WriteLine(workQueue.IsEmpty()); sw.Close(); } static void workQueue_UserWork( object sender, WorkQueue < int > .EnqueueEventArgs e) { StringBuilder sb = new StringBuilder(); sb.Append(e.Item).Append( " \t\t " ).Append(DateTime.Now.ToString( " u " ) + " \t\t " ).Append(Thread.CurrentThread.ManagedThreadId); list.Add(sb.ToString()); Thread.Sleep( 15 ); } } }
复制代码

 

[csharp]  view plain copy
  1. using System;  
  2.   
  3. using System.Threading;  
  4.   
  5. using System.Collections;  
  6.   
  7. using System.Collections.Generic;  
  8.   
  9.   
  10. // 将线程同步事件封装在此类中,   
  11.   
  12. // 以便于将这些事件传递给 Consumer 和  
  13.   
  14. // Producer 类。  
  15.   
  16. public class SyncEvents  
  17.   
  18. {  
  19.   
  20.     public SyncEvents()  
  21.   
  22.     {  
  23.   
  24.         // AutoResetEvent 用于“新项”事件,因为  
  25.   
  26.         // 我们希望每当使用者线程响应此事件时,  
  27.   
  28.         // 此事件就会自动重置。  
  29.   
  30.         _newItemEvent = new AutoResetEvent(false);  
  31.   
  32.   
  33.         // ManualResetEvent 用于“退出”事件,因为  
  34.   
  35.         // 我们希望发出此事件的信号时有多个线程响应。  
  36.   
  37.         // 如果使用 AutoResetEvent,事件  
  38.   
  39.         // 对象将在单个线程作出响应之后恢复为   
  40.   
  41.         // 未发信号的状态,而其他线程将  
  42.   
  43.         // 无法终止。  
  44.   
  45.         _exitThreadEvent = new ManualResetEvent(false);  
  46.   
  47.   
  48.         // 这两个事件也放在一个 WaitHandle 数组中,以便  
  49.   
  50.         // 使用者线程可以使用 WaitAny 方法  
  51.   
  52.         // 阻塞这两个事件。  
  53.   
  54.         _eventArray = new WaitHandle[2];  
  55.   
  56.         _eventArray[0] = _newItemEvent;  
  57.   
  58.         _eventArray[1] = _exitThreadEvent;  
  59.   
  60.     }  
  61.   
  62.   
  63.     // 公共属性允许对事件进行安全访问。  
  64.   
  65.     public EventWaitHandle ExitThreadEvent  
  66.   
  67.     {  
  68.   
  69.         get { return _exitThreadEvent; }  
  70.   
  71.     }  
  72.   
  73.     public EventWaitHandle NewItemEvent  
  74.   
  75.     {  
  76.   
  77.         get { return _newItemEvent; }  
  78.   
  79.     }  
  80.   
  81.     public WaitHandle[] EventArray  
  82.   
  83.     {  
  84.   
  85.         get { return _eventArray; }  
  86.   
  87.     }  
  88.   
  89.   
  90.     private EventWaitHandle _newItemEvent;  
  91.   
  92.     private EventWaitHandle _exitThreadEvent;  
  93.   
  94.     private WaitHandle[] _eventArray;  
  95.   
  96. }  
  97.   
  98.   
  99. // Producer 类(使用一个辅助线程)  
  100.   
  101. // 将项异步添加到队列中,共添加 20 个项。  
  102.   
  103. public class Producer   
  104.   
  105. {  
  106.   
  107.     public Producer(Queue<int> q, SyncEvents e)  
  108.   
  109.     {  
  110.   
  111.         _queue = q;  
  112.   
  113.         _syncEvents = e;  
  114.   
  115.     }  
  116.   
  117.     public void ThreadRun()  
  118.   
  119.     {  
  120.   
  121.         int count = 0;  
  122.   
  123.         Random r = new Random();  
  124.   
  125.         while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))  
  126.   
  127.         {  
  128.   
  129.             lock (((ICollection)_queue).SyncRoot)  
  130.   
  131.             {  
  132.   
  133.                 while (_queue.Count < 20)  
  134.   
  135.                 {  
  136.   
  137.                     _queue.Enqueue(r.Next(0, 100));  
  138.   
  139.                     _syncEvents.NewItemEvent.Set();  
  140.   
  141.                     count++;  
  142.   
  143.                 }  
  144.   
  145.             }  
  146.   
  147.         }  
  148.   
  149.         Console.WriteLine("Producer thread: produced {0} items", count);  
  150.   
  151.     }  
  152.   
  153.     private Queue<int> _queue;  
  154.   
  155.     private SyncEvents _syncEvents;  
  156.   
  157. }  
  158.   
  159.   
  160. // Consumer 类通过自己的辅助线程使用队列  
  161.   
  162. // 中的项。Producer 类使用 NewItemEvent   
  163.   
  164. // 将新项通知 Consumer 类。  
  165.   
  166. public class Consumer  
  167.   
  168. {  
  169.   
  170.     public Consumer(Queue<int> q, SyncEvents e)  
  171.   
  172.     {  
  173.   
  174.         _queue = q;  
  175.   
  176.         _syncEvents = e;  
  177.   
  178.     }  
  179.   
  180.     public void ThreadRun()  
  181.   
  182.     {  
  183.   
  184.         int count = 0;  
  185.   
  186.         while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)  
  187.   
  188.         {  
  189.   
  190.             lock (((ICollection)_queue).SyncRoot)  
  191.   
  192.             {  
  193.   
  194.                 int item = _queue.Dequeue();  
  195.   
  196.             }  
  197.   
  198.             count++;  
  199.   
  200.         }  
  201.   
  202.         Console.WriteLine("Consumer Thread: consumed {0} items", count);  
  203.   
  204.     }  
  205.   
  206.     private Queue<int> _queue;  
  207.   
  208.     private SyncEvents _syncEvents;  
  209.   
  210. }  
  211.   
  212.   
  213. public class ThreadSyncSample  
  214.   
  215. {  
  216.   
  217.     private static void ShowQueueContents(Queue<int> q)  
  218.   
  219.     {  
  220.   
  221.         // 对集合进行枚举本来就不是线程安全的,  
  222.   
  223.         // 因此在整个枚举过程中锁定集合以防止  
  224.   
  225.         // 使用者和制造者线程修改内容  
  226.   
  227.         // 是绝对必要的。(此方法仅由  
  228.   
  229.         // 主线程调用。)  
  230.   
  231.         lock (((ICollection)q).SyncRoot)  
  232.   
  233.         {  
  234.   
  235.             foreach (int i in q)  
  236.   
  237.             {  
  238.   
  239.                 Console.Write("{0} ", i);  
  240.   
  241.             }  
  242.   
  243.         }  
  244.   
  245.         Console.WriteLine();  
  246.   
  247.     }  
  248.   
  249.   
  250.     static void Main()  
  251.   
  252.     {  
  253.   
  254.         // 配置结构,该结构包含线程同步  
  255.   
  256.         // 所需的事件信息。  
  257.   
  258.         SyncEvents syncEvents = new SyncEvents();  
  259.   
  260.   
  261.         // 泛型队列集合用于存储要制造和使用的  
  262.   
  263.         // 项。此例中使用的是“int”。  
  264.   
  265.         Queue<int> queue = new Queue<int>();  
  266.   
  267.   
  268.         // 创建对象,一个用于制造项,一个用于  
  269.   
  270.         // 使用项。将队列和线程同步事件传递给  
  271.   
  272.         // 这两个对象。  
  273.   
  274.         Console.WriteLine("Configuring worker threads...");  
  275.   
  276.         Producer producer = new Producer(queue, syncEvents);  
  277.   
  278.         Consumer consumer = new Consumer(queue, syncEvents);  
  279.   
  280.   
  281.         // 为制造者对象和使用者对象创建线程  
  282.   
  283.         // 对象。此步骤并不创建或启动  
  284.   
  285.         // 实际线程。  
  286.   
  287.         Thread producerThread = new Thread(producer.ThreadRun);  
  288.   
  289.         Thread consumerThread = new Thread(consumer.ThreadRun);  
  290.   
  291.   
  292.         // 创建和启动两个线程。  
  293.   
  294.         Console.WriteLine("Launching producer and consumer threads...");          
  295.   
  296.         producerThread.Start();  
  297.   
  298.         consumerThread.Start();  
  299.   
  300.   
  301.         // 为制造者线程和使用者线程设置 10 秒的运行时间。  
  302.   
  303.         // 使用主线程(执行此方法的线程)  
  304.   
  305.         // 每隔 2.5 秒显示一次队列内容。  
  306.   
  307.         for (int i = 0; i < 4; i++)  
  308.   
  309.         {  
  310.   
  311.             Thread.Sleep(2500);  
  312.   
  313.             ShowQueueContents(queue);  
  314.   
  315.         }  
  316.   
  317.   
  318.         // 向使用者线程和制造者线程发出终止信号。  
  319.   
  320.         // 这两个线程都会响应,由于 ExitThreadEvent 是  
  321.   
  322.         // 手动重置的事件,因此除非显式重置,否则将保持“设置”。  
  323.   
  324.         Console.WriteLine("Signaling threads to terminate...");  
  325.   
  326.         syncEvents.ExitThreadEvent.Set();  
  327.   
  328.   
  329.         // 使用 Join 阻塞主线程,首先阻塞到制造者线程  
  330.   
  331.         // 终止,然后阻塞到使用者线程终止。  
  332.   
  333.         Console.WriteLine("main thread waiting for threads to finish...");  
  334.   
  335.         producerThread.Join();  
  336.   
  337.         consumerThread.Join();  
  338.   
  339.     }  
  340.   
  341. }  
[sql]  view plain copy
  1. namespace WindowsFormsApplication1  
  2. {  
  3.     public partial class Form3 : Form  
  4.     {  
  5.         public Form3()  
  6.         {  
  7.             InitializeComponent();  
  8.         }  
  9.         public delegate void Delegate1();  
  10.         public delegate void Delegate2(DataTable dt);  
  11.         public void buttonFind_Click(object sender, EventArgs e)  
  12.         {  
  13.             Delegate1 d1 = new Delegate1(Find);  
  14.             d1.BeginInvoke(new AsyncCallback(AsyncCallback1), d1);  
  15.         }  
  16.         public void AsyncCallback1(IAsyncResult iAsyncResult)  
  17.         {  
  18.             Delegate1 d1 = (Delegate1)iAsyncResult.AsyncState;  
  19.             d1.EndInvoke(iAsyncResult);  
  20.         }  
  21.         public void Find()  
  22.         {  
  23.             DataTable dt = new DataTable();  
  24.             dt.Columns.Add("name", typeof(string));  
  25.             dt.Columns.Add("age", typeof(int));  
  26.             AddRow(dt, "张三", 19);  
  27.             AddRow(dt, "张三", 19);  
  28.             AddRow(dt, "李四", 18);  
  29.             this.Invoke(new Delegate2(Bind2), new object[] { dt });  
  30.         }  
  31.         public void AddRow(DataTable dt, string nameint age)  
  32.         {  
  33.             DataRow dr = dt.NewRow();  
  34.             dr["name"] = name;  
  35.             dr["age"] = age;  
  36.             dt.Rows.Add(dr);  
  37.         }  
  38.         public void Bind2(DataTable dt)  
  39.         {  
  40.             this.dataGridView1.DataSource = dt;  
  41.         }  
  42.     }  
  43. }  

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值