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


    [csharp] view plaincopy
    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. }  
    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. }  
  • 相关阅读:
    MySQL效能监控工具mysqlreport安装和中文说明
    mysql的配置文件my.cnf
    MySQL的高可用设计方案的记录
    jQuery 求页面加载等待特效
    如果客户端禁用cookie,session还能使用吗?
    heartbeat重要文件的配置参数说明
    MySQL的索引类型和左前缀索引
    比较一下Linux下的Epoll模型和select模型的区别
    网络防火墙和NAT地址转换
    Postfix+dovecot搭建简单邮箱服务器
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/3110500.html
Copyright © 2020-2023  润新知