c# 多线程排队队列实现的源码

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

  1. using System;  

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

using System; using System.Threading; using System.Collections; using System.Collections.Generic; // 将线程同步事件封装在此类中, // 以便于将这些事件传递给 Consumer 和 // Producer 类。 public class SyncEvents { public SyncEvents() { // AutoResetEvent 用于“新项”事件,因为 // 我们希望每当使用者线程响应此事件时, // 此事件就会自动重置。 _newItemEvent = new AutoResetEvent(false); // ManualResetEvent 用于“退出”事件,因为 // 我们希望发出此事件的信号时有多个线程响应。 // 如果使用 AutoResetEvent,事件 // 对象将在单个线程作出响应之后恢复为 // 未发信号的状态,而其他线程将 // 无法终止。 _exitThreadEvent = new ManualResetEvent(false); // 这两个事件也放在一个 WaitHandle 数组中,以便 // 使用者线程可以使用 WaitAny 方法 // 阻塞这两个事件。 _eventArray = new WaitHandle[2]; _eventArray[0] = _newItemEvent; _eventArray[1] = _exitThreadEvent; } // 公共属性允许对事件进行安全访问。 public EventWaitHandle ExitThreadEvent { get { return _exitThreadEvent; } } public EventWaitHandle NewItemEvent { get { return _newItemEvent; } } public WaitHandle[] EventArray { get { return _eventArray; } } private EventWaitHandle _newItemEvent; private EventWaitHandle _exitThreadEvent; private WaitHandle[] _eventArray; } // Producer 类(使用一个辅助线程) // 将项异步添加到队列中,共添加 20 个项。 public class Producer { public Producer(Queue<int> q, SyncEvents e) { _queue = q; _syncEvents = e; } public void ThreadRun() { int count = 0; Random r = new Random(); while (!_syncEvents.ExitThreadEvent.WaitOne(0, false)) { lock (((ICollection)_queue).SyncRoot) { while (_queue.Count < 20) { _queue.Enqueue(r.Next(0, 100)); _syncEvents.NewItemEvent.Set(); count++; } } } Console.WriteLine("Producer thread: produced {0} items", count); } private Queue<int> _queue; private SyncEvents _syncEvents; } // Consumer 类通过自己的辅助线程使用队列 // 中的项。Producer 类使用 NewItemEvent // 将新项通知 Consumer 类。 public class Consumer { public Consumer(Queue<int> q, SyncEvents e) { _queue = q; _syncEvents = e; } public void ThreadRun() { int count = 0; while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1) { lock (((ICollection)_queue).SyncRoot) { int item = _queue.Dequeue(); } count++; } Console.WriteLine("Consumer Thread: consumed {0} items", count); } private Queue<int> _queue; private SyncEvents _syncEvents; } public class ThreadSyncSample { private static void ShowQueueContents(Queue<int> q) { // 对集合进行枚举本来就不是线程安全的, // 因此在整个枚举过程中锁定集合以防止 // 使用者和制造者线程修改内容 // 是绝对必要的。(此方法仅由 // 主线程调用。) lock (((ICollection)q).SyncRoot) { foreach (int i in q) { Console.Write("{0} ", i); } } Console.WriteLine(); } static void Main() { // 配置结构,该结构包含线程同步 // 所需的事件信息。 SyncEvents syncEvents = new SyncEvents(); // 泛型队列集合用于存储要制造和使用的 // 项。此例中使用的是“int”。 Queue<int> queue = new Queue<int>(); // 创建对象,一个用于制造项,一个用于 // 使用项。将队列和线程同步事件传递给 // 这两个对象。 Console.WriteLine("Configuring worker threads..."); Producer producer = new Producer(queue, syncEvents); Consumer consumer = new Consumer(queue, syncEvents); // 为制造者对象和使用者对象创建线程 // 对象。此步骤并不创建或启动 // 实际线程。 Thread producerThread = new Thread(producer.ThreadRun); Thread consumerThread = new Thread(consumer.ThreadRun); // 创建和启动两个线程。 Console.WriteLine("Launching producer and consumer threads..."); producerThread.Start(); consumerThread.Start(); // 为制造者线程和使用者线程设置 10 秒的运行时间。 // 使用主线程(执行此方法的线程) // 每隔 2.5 秒显示一次队列内容。 for (int i = 0; i < 4; i++) { Thread.Sleep(2500); ShowQueueContents(queue); } // 向使用者线程和制造者线程发出终止信号。 // 这两个线程都会响应,由于 ExitThreadEvent 是 // 手动重置的事件,因此除非显式重置,否则将保持“设置”。 Console.WriteLine("Signaling threads to terminate..."); syncEvents.ExitThreadEvent.Set(); // 使用 Join 阻塞主线程,首先阻塞到制造者线程 // 终止,然后阻塞到使用者线程终止。 Console.WriteLine("main thread waiting for threads to finish..."); producerThread.Join(); consumerThread.Join(); } }

  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. }  

namespace WindowsFormsApplication1 { public partial class Form3 : Form { public Form3() { InitializeComponent(); } public delegate void Delegate1(); public delegate void Delegate2(DataTable dt); public void buttonFind_Click(object sender, EventArgs e) { Delegate1 d1 = new Delegate1(Find); d1.BeginInvoke(new AsyncCallback(AsyncCallback1), d1); } public void AsyncCallback1(IAsyncResult iAsyncResult) { Delegate1 d1 = (Delegate1)iAsyncResult.AsyncState; d1.EndInvoke(iAsyncResult); } public void Find() { DataTable dt = new DataTable(); dt.Columns.Add("name", typeof(string)); dt.Columns.Add("age", typeof(int)); AddRow(dt, "张三", 19); AddRow(dt, "张三", 19); AddRow(dt, "李四", 18); this.Invoke(new Delegate2(Bind2), new object[] { dt }); } public void AddRow(DataTable dt, string name, int age) { DataRow dr = dt.NewRow(); dr["name"] = name; dr["age"] = age; dt.Rows.Add(dr); } public void Bind2(DataTable dt) { this.dataGridView1.DataSource = dt; } } }



posted on 2012-04-28 13:01 Hao_Guo 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/HaoGuo/archive/2012/04/28/thread.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值