今天是圣诞节,大家 Merry Chrismas~
以前都是在C++项目中写界面,现在接触了C#感觉比MFC和QT好用多了,决定以后除了特殊要求外都用C#开发:)。记录一下用C#实现生产者消费者模式吧。
先介绍一下这个模式,简而言之就是生产者(可能有数个)生产东西,消费者(可能有数个)消费前面生产的东西。举个生活中的例子就是苹果有好几个厂家(生产者)生产iphone,线下线上的购买者(消费者)通过多种途径消耗掉iphone的库存。再举一个实际开发中的例子,我架设了四个摄像头同时不间断拍照,我需要不断的处理得到的图片,这也是生产者消费者模式。
这次演示用到的类文件还是以前用过的,产生随机数,链接如下:
https://blog.csdn.net/li3781695/article/details/84981827
先把界面弄的和这一样。

然后就可以开始了,直接上代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;namespace Producer_Consumer_Test
{public partial class Form1 : Form{bool NeedsStop = false;bool NeedsStop1 = false;bool NeedsStop2 = false;bool NeedsStop3 = false;bool NeedsStop4 = false;Object thisLock = new Object();List<int> RandomList = new List<int>();public Form1(){InitializeComponent();}/***********************************************生产者按钮与消费者按钮**********************************************/private void btn_Use_Start_Click(object sender, EventArgs e){btn_Use_Start.Text = (btn_Use_Start.Text == "开始消费") ? "停止消费" : "开始消费";if (btn_Use_Start.Text == "停止消费"){Thread Mythread1 = new Thread(Consumer1);Mythread1.Start();Thread Mythread2 = new Thread(Consumer2);Mythread2.Start();NeedsStop = false;}else NeedsStop = true;}private void btn_Producer1_Start_Click(object sender, EventArgs e){btn_Producer1_Start.Text = (btn_Producer1_Start.Text == "开始生产") ? "停止生产" : "开始生产";if (btn_Producer1_Start.Text == "停止生产"){Thread Mythread = new Thread(Thread1_Random);Mythread.Start();NeedsStop1 = false;}else  NeedsStop1 = true;}private void btn_Producer2_Start_Click(object sender, EventArgs e){btn_Producer2_Start.Text = (btn_Producer2_Start.Text == "开始生产") ? "停止生产" : "开始生产";if (btn_Producer2_Start.Text == "停止生产"){Thread Mythread = new Thread(Thread2_Random);Mythread.Start();NeedsStop2 = false;}else  NeedsStop2 = true;}private void btn_Producer3_Start_Click(object sender, EventArgs e){btn_Producer3_Start.Text = (btn_Producer3_Start.Text == "开始生产") ? "停止生产" : "开始生产";if (btn_Producer3_Start.Text == "停止生产"){Thread Mythread = new Thread(Thread3_Random);Mythread.Start();NeedsStop3 = false;}else  NeedsStop3 = true;}private void btn_Producer4_Start_Click(object sender, EventArgs e){btn_Producer4_Start.Text = (btn_Producer4_Start.Text == "开始生产") ? "停止生产" : "开始生产";if (btn_Producer4_Start.Text == "停止生产"){Thread Mythread = new Thread(Thread4_Random);Mythread.Start();NeedsStop4 = false;}else  NeedsStop4 = true;}/***********************************************线程函数**********************************************/private void Thread1_Random(){MyRandom Ran = new MyRandom();Ran.IsEven += new IsEvenEvent(SaveData);while (true){Ran.run_Random();if (NeedsStop1 == true) break;Thread.Sleep(500);}}private void Thread2_Random(){MyRandom Ran = new MyRandom();Ran.IsEven += new IsEvenEvent(SaveData);while (true){Ran.run_Random();if (NeedsStop2 == true) break;Thread.Sleep(500);}}private void Thread3_Random(){MyRandom Ran = new MyRandom();Ran.IsEven += new IsEvenEvent(SaveData);while (true){Ran.run_Random();if (NeedsStop3 == true) break;Thread.Sleep(500);}}private void Thread4_Random(){MyRandom Ran = new MyRandom();Ran.IsEven += new IsEvenEvent(SaveData);while (true){Ran.run_Random();if (NeedsStop4== true) break;Thread.Sleep(500);}}//此函数将四个生产者线程产生的随机数压栈,此处用互斥锁锁住防止多线程同时访问private void SaveData(object Sender, IsEvenEventArgs e){lock (thisLock){RandomList.Add(e.Random);}}//消费者处理函数,数据处理区用锁锁住private void Consumer1(){while (true){if (NeedsStop == true) break;Thread.Sleep(100);lock (thisLock){if (RandomList.Count == 0) continue;if (RandomList.ElementAt(0) % 2 == 0){textBox_Consumer1.Invoke(new Action(delegate{textBox_Consumer1.Text += RandomList.ElementAt(0).ToString()+"\r\n";RandomList.RemoveAt(0);textBox_Consumer1.Focus();//获取焦点textBox_Consumer1.Select(this.textBox_Consumer1.TextLength, 0);//光标定位到文本最后textBox_Consumer1.ScrollToCaret();//滚动到光标处}));}else RandomList.RemoveAt(0);}}}private void Consumer2(){while (true){if (NeedsStop == true) break;Thread.Sleep(100);lock (thisLock){if (RandomList.Count == 0) continue;if (RandomList.ElementAt(0) % 2 == 0){ textBox_Consumer2.Invoke(new Action(delegate{textBox_Consumer2.Text += RandomList.ElementAt(0).ToString() + "\r\n";RandomList.RemoveAt(0);textBox_Consumer2.Focus();//获取焦点textBox_Consumer2.Select(this.textBox_Consumer2.TextLength, 0);//光标定位到文本最后textBox_Consumer2.ScrollToCaret();//滚动到光标处}));}else RandomList.RemoveAt(0);}}}}
}

先提一下生产随机数的类吧,自定义了一个事件,生成随机数的事件将偶数传回。
整个流程大致是:
1.按下开始消费按钮后,开启两个消费者线程,等待从链表头部得到数据,如得到就直接打印到文本框(两个消费者就开始如狼似虎的等待在apple专卖店门口,等待从多个工厂运过来的新款iphone)。
2.按下四个“开始生产”按钮以后,四个生产者不断触发随机数,得到的随机数将使用SaveData函数存入链表尾部(被生产出来的iphone就被两个消费者疯狂买买买,两个文本框就是这两个消费者的购物清单)。
3.此处涉及到此链表的地方都用互斥锁锁起来防止多线程同时访问同一块数据,这个模式也可以应用在图像处理上,这个也是一个用途十分广泛的模式。

关于生产者消费者模式的C#实现相关推荐

  1. 【C++】多线程(链式、循环队列)实现生产者消费者模式

    生产者消费者模式:         生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同 ...

  2. 面试官让我手写一个生产者消费者模式?

    不知道你是否遇到过面试官让你手写生产者消费者代码.别说,前段时间有小伙伴还真的遇到了这种情况,当时是一脸懵逼. 但是,俗话说,从哪里跌倒就要从哪里爬起来.既然这次被问到了,那就回去好好研究一下,争取下 ...

  3. java lock condition_Java 通过 Lock 和 竞争条件 Condition 实现生产者消费者模式

    更多 Java 并发编程方面的文章,请参见文集<Java 并发编程> 竞争条件 多个线程共享对某些变量的访问,其最后结果取决于哪个线程偶然在竞争中获胜. condition.await() ...

  4. 生产者/消费者模式(阻塞队列)

    生产消费者模式  貌似也是阻塞的问题  花了一些时间终于弄明白这个鸟东东,以前还以为是不复杂的一个东西的,以前一直以为和观察者模式差不多(其实也是差不多的,呵呵),生产消费者模式应该是可以通过观察者模 ...

  5. 多线程终极模式:生产者-消费者模式

    多线程de小事情 导航不迷路: 程序.进程以及线程的爱恨情仇 最简单实现多线程的方法(Thread) 简单易懂的多线程(通过实现Runnable接口实现多线程) 常用获取线程基本信息的方法(新手专属) ...

  6. Java中设计模式之生产者消费者模式-3

    引言 生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区.其中一个是生产者,用于将消息放入缓冲区:另 ...

  7. 单线程下的生产者--消费者模式详解,wait和sleep的区别

    1. 单线程下的生产者--消费者模式 1.1 该模式下,一个线程生产数据,另一个线程处理数据.当数据还没被处理,那么生产数据的线程进入等待状态:如果数据还没生产,那么处理数据的线程进入等待状态,代码及 ...

  8. java消费者模式_基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  9. [19/04/11-星期四] 多线程_并发协作(生产者/消费者模式_2种解决方案(管程法和信号灯法))...

    一.概念 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型"生产者/消费者模式". Ø 什么是生产者? 生产者指的是负责生产数据的模 ...

  10. Java并发程序设计(十一)设计模式与并发之生产者-消费者模式

    设计模式与并发之生产者-消费者模式 生产者-消费者模式是一个经典的多线程设计模式.它为多线程间的协作提供了良好的解决方案. 在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程 ...

最新文章

  1. 表面积最小(POJ3536)
  2. 微信二次修改微信号_如何二次修改微信号?简单易懂教程
  3. OVS使用笔记(四十三)
  4. ACL 2020 | 多跳问答的基于对齐的无监督迭代解释检索方法
  5. Esper epl语句实验
  6. matex2推送鸿蒙系统,拜拜了,Powered by Android!
  7. gitlab和github一起使用
  8. vue-awesome-swiper:依赖于6.X版本Swiper时autoplay自动播放设置无效
  9. VM ware下载教程
  10. COOC6.2增加同义词合并无意义词删除等功能
  11. 《临江仙》---摘抄
  12. 计算机加密解除,bitlocker加密如何取消?Win7系统电脑取消bitlocker加密的方法
  13. 小学生的搞笑考试卷子
  14. 共享单车泡沫破灭,自行车产业链的每个环节都被波及
  15. rsync运行时出现skipping non-regular file
  16. and true和if都是python语言的保留字_python自学 第三章 python语言基础之保留字、标识符与内置函数...
  17. Flask开发成语接龙游戏,以后闲了手机玩玩自己写的游戏吧!
  18. 高校校园跑腿系统的设计app-计算机毕业设计
  19. 【论文学习笔记-10】ActiveStereoNet(Google ECCV2018)主动式双目相机自监督学习立体匹配网络
  20. 用Python画红旗

热门文章

  1. vscode+django 搭建自己的个人网站(一) ——环境搭建与配置
  2. 三菱R系列ST、RD77MS定位以及三菱触摸屏配方功能,此案例还提供两个触摸屏实现异地操作,使操作更加方便快捷
  3. 转发(forword)和重定向(redirect)
  4. 如何描述PCIe SSD性能的稳定性?
  5. placeholder传入值
  6. Please enable JavaScript to continue.
  7. ERR Client sent AUTH, but no password is set. channel: [id: 0xfca52a0c, L:/1
  8. linux测试x11,Linux GUI自动化测试工具x11 GUITest in Linux x86
  9. C语言实现读者写者问题(读者优先)
  10. JavaScript-怪癖检测