[csharp] view plaincopy

  1. using System;
  2. using System.Threading;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. // 将线程同步事件封装在此类中,
  6. // 以便于将这些事件传递给 Consumer 和
  7. // Producer 类。
  8. public class SyncEvents
  9. {
  10. public SyncEvents()
  11. {
  12. // AutoResetEvent 用于“新项”事件,因为
  13. // 我们希望每当使用者线程响应此事件时,
  14. // 此事件就会自动重置。
  15. _newItemEvent = new AutoResetEvent(false);
  16. // ManualResetEvent 用于“退出”事件,因为
  17. // 我们希望发出此事件的信号时有多个线程响应。
  18. // 如果使用 AutoResetEvent,事件
  19. // 对象将在单个线程作出响应之后恢复为
  20. // 未发信号的状态,而其他线程将
  21. // 无法终止。
  22. _exitThreadEvent = new ManualResetEvent(false);
  23. // 这两个事件也放在一个 WaitHandle 数组中,以便
  24. // 使用者线程可以使用 WaitAny 方法
  25. // 阻塞这两个事件。
  26. _eventArray = new WaitHandle[2];
  27. _eventArray[0] = _newItemEvent;
  28. _eventArray[1] = _exitThreadEvent;
  29. }
  30. // 公共属性允许对事件进行安全访问。
  31. public EventWaitHandle ExitThreadEvent
  32. {
  33. get { return _exitThreadEvent; }
  34. }
  35. public EventWaitHandle NewItemEvent
  36. {
  37. get { return _newItemEvent; }
  38. }
  39. public WaitHandle[] EventArray
  40. {
  41. get { return _eventArray; }
  42. }
  43. private EventWaitHandle _newItemEvent;
  44. private EventWaitHandle _exitThreadEvent;
  45. private WaitHandle[] _eventArray;
  46. }
  47. // Producer 类(使用一个辅助线程)
  48. // 将项异步添加到队列中,共添加 20 个项。
  49. public class Producer
  50. {
  51. public Producer(Queue<int> q, SyncEvents e)
  52. {
  53. _queue = q;
  54. _syncEvents = e;
  55. }
  56. public void ThreadRun()
  57. {
  58. int count = 0;
  59. Random r = new Random();
  60. while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
  61. {
  62. lock (((ICollection)_queue).SyncRoot)
  63. {
  64. while (_queue.Count < 20)
  65. {
  66. _queue.Enqueue(r.Next(0, 100));
  67. _syncEvents.NewItemEvent.Set();
  68. count++;
  69. }
  70. }
  71. }
  72. Console.WriteLine("Producer thread: produced {0} items", count);
  73. }
  74. private Queue<int> _queue;
  75. private SyncEvents _syncEvents;
  76. }
  77. // Consumer 类通过自己的辅助线程使用队列
  78. // 中的项。Producer 类使用 NewItemEvent
  79. // 将新项通知 Consumer 类。
  80. public class Consumer
  81. {
  82. public Consumer(Queue<int> q, SyncEvents e)
  83. {
  84. _queue = q;
  85. _syncEvents = e;
  86. }
  87. public void ThreadRun()
  88. {
  89. int count = 0;
  90. while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
  91. {
  92. lock (((ICollection)_queue).SyncRoot)
  93. {
  94. int item = _queue.Dequeue();
  95. }
  96. count++;
  97. }
  98. Console.WriteLine("Consumer Thread: consumed {0} items", count);
  99. }
  100. private Queue<int> _queue;
  101. private SyncEvents _syncEvents;
  102. }
  103. public class ThreadSyncSample
  104. {
  105. private static void ShowQueueContents(Queue<int> q)
  106. {
  107. // 对集合进行枚举本来就不是线程安全的,
  108. // 因此在整个枚举过程中锁定集合以防止
  109. // 使用者和制造者线程修改内容
  110. // 是绝对必要的。(此方法仅由
  111. // 主线程调用。)
  112. lock (((ICollection)q).SyncRoot)
  113. {
  114. foreach (int i in q)
  115. {
  116. Console.Write("{0} ", i);
  117. }
  118. }
  119. Console.WriteLine();
  120. }
  121. static void Main()
  122. {
  123. // 配置结构,该结构包含线程同步
  124. // 所需的事件信息。
  125. SyncEvents syncEvents = new SyncEvents();
  126. // 泛型队列集合用于存储要制造和使用的
  127. // 项。此例中使用的是“int”。
  128. Queue<int> queue = new Queue<int>();
  129. // 创建对象,一个用于制造项,一个用于
  130. // 使用项。将队列和线程同步事件传递给
  131. // 这两个对象。
  132. Console.WriteLine("Configuring worker threads...");
  133. Producer producer = new Producer(queue, syncEvents);
  134. Consumer consumer = new Consumer(queue, syncEvents);
  135. // 为制造者对象和使用者对象创建线程
  136. // 对象。此步骤并不创建或启动
  137. // 实际线程。
  138. Thread producerThread = new Thread(producer.ThreadRun);
  139. Thread consumerThread = new Thread(consumer.ThreadRun);
  140. // 创建和启动两个线程。
  141. Console.WriteLine("Launching producer and consumer threads...");
  142. producerThread.Start();
  143. consumerThread.Start();
  144. // 为制造者线程和使用者线程设置 10 秒的运行时间。
  145. // 使用主线程(执行此方法的线程)
  146. // 每隔 2.5 秒显示一次队列内容。
  147. for (int i = 0; i < 4; i++)
  148. {
  149. Thread.Sleep(2500);
  150. ShowQueueContents(queue);
  151. }
  152. // 向使用者线程和制造者线程发出终止信号。
  153. // 这两个线程都会响应,由于 ExitThreadEvent 是
  154. // 手动重置的事件,因此除非显式重置,否则将保持“设置”。
  155. Console.WriteLine("Signaling threads to terminate...");
  156. syncEvents.ExitThreadEvent.Set();
  157. // 使用 Join 阻塞主线程,首先阻塞到制造者线程
  158. // 终止,然后阻塞到使用者线程终止。
  159. Console.WriteLine("main thread waiting for threads to finish...");
  160. producerThread.Join();
  161. consumerThread.Join();
  162. }
  163. }
  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 name, int 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. }

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

c# 多线程排队队列实现的源码的更多相关文章

  1. 延迟队列DelayQueue take() 源码分析

    延迟队列DelayQueue take() 源码分析 在工作中使用了延迟队列,对其内部的实现很好奇,于是就研究了一下其运行原理,在这里就介绍一下take()方法的源码 1 take()源码 如下所示 ...

  2. Java多线程学习之线程池源码详解

    0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...

  3. Android多线程:深入分析 Handler机制源码(二)

    前言 在Android开发的多线程应用场景中,Handler机制十分常用 接下来,深入分析 Handler机制的源码,希望加深理解 目录 1. Handler 机制简介 定义一套 Android 消息 ...

  4. 自己实现多线程的socket,socketserver源码剖析

    1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...

  5. 10 DelayQueue 延时队列类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 www.cnblogs.com/oloroso/ 本文由乌合 ...

  6. java并发包——阻塞队列BlockingQueue及源码分析

    一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...

  7. 【RabbitMQ学习记录】- 消息队列存储机制源码分析

    本文来自 网易云社区 . RabbitMQ在金融系统,OpenStack内部组件通信和通信领域应用广泛,它部署简单,管理界面内容丰富使用十分方便.笔者最近在研究RabbitMQ部署运维和代码架构,本篇 ...

  8. JAVA并发(7)-并发队列PriorityBlockingQueue的源码分析

    本文讲PriorityBlockingQueue(优先阻塞队列) 1. 介绍 一个无界的具有优先级的阻塞队列,使用跟PriorityQueue相同的顺序规则,默认顺序是自然顺序(从小到大).若传入的对 ...

  9. ucos队列的实现--源码分析

    之前说到事件,讲了事件,信号量和互斥信号量,还有一个队列没说,今天说说队列. 队列是用在任务之间传送多个消息的时候,a任务发送消息,b任务发送消息,然后c任务可以依次去提取出b和a传递的消息,不会造成 ...

随机推荐

  1. notepad++设置右键

    Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\Shell\NotePad++][HKEY_CLASSES_ROOT\*\Shell\ ...

  2. learning uboot test command

    uboot commad test test - minimal test like /bin/sh so we can use test command to some judge for exam ...

  3. kmp算法中的nextval实例解释

    求nextval数组值有两种方法,一种是不依赖next数组值直接用观察法求得,一种方法是根据next数组值进行推理,两种方法均可使用,视更喜欢哪种方法而定. 本文主要分析nextval数组值的第二种方 ...

  4. [HTML]去除li前面的小黑点,和ul、LI部分属性

    [转] 对于很多人用div来做网站时,总会用到,但在显示效果时前面总是会有一个小黑点,这个令很多人头痛,但又找不到要源,其它我们可以用以下方法来清除.[HTML]去除li前面的小黑点,和ul.LI部分 ...

  5. php变量什么情况下加大括号{}

    下面几个比较能说明原因的解释是: 表示{}里面的是一个变量  ,执行时按照变量来处理 在字符串中引用变量使用的特殊包括方式,这样就可以不使用.运算符,从而减少代码的输入量了. 其实输出那块是等同于pr ...

  6. Jenkins自动化部署代码

    通过jenkins自动化部署项目代码可以大幅度节省打包上传部署的时间,提高开发测试的工作效率 ========== 完美的分割线 =========== 1.Jenkins是什么 1)Jenkins是 ...

  7. C高级第一次PTA作业(2)

    6-1 在数组中查找指定元素 本题要求实现一个在数组中查找指定元素的简单函数. 1.设计思路 (1)算法: 第一步:定义一个数组名为a的数组,循环变量i,需要查找的数x,和数组元素的个数n. 第二步: ...

  8. 2018-2019-2 20165212 《网络对抗技术》Exp3 免杀原理与实践

    2018-2019-2 20165212 <网络对抗技术>Exp3 免杀原理与实践 一.实验内容 正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion ...

  9. hdu2073-2078

    hdu2073 数学 #include<stdio.h> #include<math.h> double len(double x){ )*(x+)); } int main( ...

  10. 【CQOI2008】中位数

    题不难,但是思路有意思,这个是我自己想出来的OvO 原题: 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. n<= ...