c# 多线程排队队列实现的源码
- 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();
- }
- }
- 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;
- }
- }
http://blog.csdn.net/loveandangle/article/details/6733642
c# 多线程排队队列实现的源码的更多相关文章
- 延迟队列DelayQueue take() 源码分析
延迟队列DelayQueue take() 源码分析 在工作中使用了延迟队列,对其内部的实现很好奇,于是就研究了一下其运行原理,在这里就介绍一下take()方法的源码 1 take()源码 如下所示 ...
- Java多线程学习之线程池源码详解
0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...
- Android多线程:深入分析 Handler机制源码(二)
前言 在Android开发的多线程应用场景中,Handler机制十分常用 接下来,深入分析 Handler机制的源码,希望加深理解 目录 1. Handler 机制简介 定义一套 Android 消息 ...
- 自己实现多线程的socket,socketserver源码剖析
1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...
- 10 DelayQueue 延时队列类——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 www.cnblogs.com/oloroso/ 本文由乌合 ...
- java并发包——阻塞队列BlockingQueue及源码分析
一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...
- 【RabbitMQ学习记录】- 消息队列存储机制源码分析
本文来自 网易云社区 . RabbitMQ在金融系统,OpenStack内部组件通信和通信领域应用广泛,它部署简单,管理界面内容丰富使用十分方便.笔者最近在研究RabbitMQ部署运维和代码架构,本篇 ...
- JAVA并发(7)-并发队列PriorityBlockingQueue的源码分析
本文讲PriorityBlockingQueue(优先阻塞队列) 1. 介绍 一个无界的具有优先级的阻塞队列,使用跟PriorityQueue相同的顺序规则,默认顺序是自然顺序(从小到大).若传入的对 ...
- ucos队列的实现--源码分析
之前说到事件,讲了事件,信号量和互斥信号量,还有一个队列没说,今天说说队列. 队列是用在任务之间传送多个消息的时候,a任务发送消息,b任务发送消息,然后c任务可以依次去提取出b和a传递的消息,不会造成 ...
随机推荐
- js上传图片前预览方法(支持预览多个图片)
运用js实现上传图片前的预览(支持多张图片),实现的例子如下: 1.源码例子: 1)Js脚本页面 <!doctype html> <html> <head> < ...
- js组件的写法
工作之中的不足,报了js培训班,因为工作加班原因缺了几天课(js组件开发),现在拾起来补补 <!doctype html> <html> <head> <me ...
- ural1469
题解: 从左往右加入每一个点 判断一下和,pre,nxt是否相交 删除得时候也要判断 代码: #pragma GCC optimize(2) #include<cstdio> #inclu ...
- C语言 string::size_type类型
string::size_type类型 从逻辑上来讲,size()成员函数似乎应该返回整型数值,或如2.2节“建议”中所述的无符号整数.但事实上,size操作返回的是string::size_type ...
- 《Python》 面向对象初识
一.面向对象初识: 1.结构上理解:类由两部分组成 class A: # class是类的关键字,类名首字母默认大写 name = 'alex' # 静态属性,静态变量,静态字段 def func ...
- CUDA ---- Kernel性能调节
Exposing Parallelism 这部分主要介绍并行分析,涉及掌握nvprof的几个metric参数,具体的这些调节为什么会影响性能会在后续博文解释. 代码准备 下面是我们的kernel函数s ...
- 数据库SQL优化大总结之 百万级数据库优化方案(转载)
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- stream_get_contents 和file_get_content的区别
stream_get_contents — 读取资源流到一个字符串, 即其读取的内容是一个已经打开的资源句柄,如fopen函数打开的文件句柄,. 而 file_get_content可以直接读取文件内 ...
- TP 模板的变量输出
- 萤石A1互联网报警盒子破解细节分析
攻击点分析: 萤石A1互联网报警盒子使用“全无线解决方案”,传感器的报警通过433.92MHz射频信号发送给报警主机,报警主机可以通过Wi-Fi联网,将报警上传萤石云端,云端会将信息推送到手机端的“ ...