本文主要讲述了多线程开发中经典示例,通过本示例,可以加深对多线程的理解。
示例概述:
下面用一个模拟吃苹果的实例,说明C#中多线程的实现方法。要求开发一个程序实现如下情况:一个家庭有三个孩子,爸爸妈妈不断削苹果往盘子里面放,老大、老二、老三不断从盘子里面取苹果吃。盘子的大小有限,最多只能放5个苹果,并且爸妈不能同时往盘子里面放苹果,妈妈具有优先权。三个孩子取苹果时,盘子不能为空,三人不能同时取,老三优先权最高,老大最低。老大吃的最快,取的频率最高,老二次之。
涉及到知识点:
线程Thread 创建并控制线程,设置其优先级并获取其状态。
锁 lock 用于实现多线程同步的最直接办法就是加锁,它可以把一段代码定义为互斥段,在一个时刻内只允许一个线程进入执行,而其他线程必须等待。
事件EventHandler 声明一个事件,用于通知界面做改变
设计思路:
Productor 表示生产者,用于削苹果。
Consumer 表示消费者,用于吃苹果。
Dish 盘子,用于装苹果,做为中间类
EatAppleSmp 的BeginEat()方法,表示开始吃苹果,启动线程
————————————————————————————————-
效果图如下【爸爸妈妈削苹果,孩子吃苹果】:
后台输出如下:
Mama放1个苹果Baba放1个苹果Dage取苹果吃...Erdi取苹果吃...Sandi等待取苹果Mama放1个苹果Sandi取苹果吃...Baba放1个苹果Dage取苹果吃...Mama放1个苹果Baba放1个苹果Erdi取苹果吃...Mama放1个苹果Baba放1个苹果Dage取苹果吃...Sandi取苹果吃...Mama放1个苹果Baba放1个苹果Erdi取苹果吃...Mama放1个苹果Baba放1个苹果Dage取苹果吃...Mama放1个苹果Baba放1个苹果Sandi取苹果吃...Mama放1个苹果Baba正在等待放入苹果Erdi取苹果吃...Baba放1个苹果Dage取苹果吃...Mama放1个苹果Baba正在等待放入苹果Mama正在等待放入苹果Sandi取苹果吃...Baba放1个苹果Mama正在等待放入苹果Erdi取苹果吃...Mama放1个苹果Dage取苹果吃...Baba放1个苹果Mama正在等待放入苹果Dage取苹果吃...Mama放1个苹果Baba正在等待放入苹果Erdi取苹果吃...Baba放1个苹果Sandi取苹果吃...Mama放1个苹果Baba正在等待放入苹果Dage取苹果吃...Baba放1个苹果Mama正在等待放入苹果Erdi取苹果吃...Mama放1个苹果Baba正在等待放入苹果Sandi取苹果吃...Baba放1个苹果Mama正在等待放入苹果Dage取苹果吃...Mama放1个苹果Baba正在等待放入苹果Mama正在等待放入苹果Erdi取苹果吃...Mama放1个苹果Baba正在等待放入苹果Dage取苹果吃...Baba放1个苹果Mama正在等待放入苹果Sandi取苹果吃...Mama放1个苹果Baba正在等待放入苹果Mama正在等待放入苹果线程 'Mama' (0x1ce0) 已退出,返回值为 0 (0x0)。线程 'Baba' (0x1888) 已退出,返回值为 0 (0x0)。Erdi取苹果吃...Dage取苹果吃...Sandi取苹果吃...Dage取苹果吃...Erdi取苹果吃...Dage等待取苹果Sandi等待取苹果Erdi等待取苹果
登录后复制
Productor 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace DemoSharp.EatApple { ////// 生产者 /// public class Productor { private Dish dish; private string name; public string Name { get { return name; } set { name = value; } } public EventHandler PutAction;//声明一个事件,当放苹果时触发该事件 public Productor(string name, Dish dish) { this.name = name; this.dish = dish; } public void run() { while (true) { bool flag= dish.Put(name); if (flag) { if (PutAction != null) { PutAction(this, null); } try { Thread.Sleep(600);//削苹果时间 } catch (Exception ex) { } } else { break; } } } } }
登录后复制
Consumer代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using DemoSharp.EatApple; namespace DemoSharp { ////// 页面类 /// public partial class EatAppleForm : Form { private EatAppleSmp m_EatAppleSmp = new EatAppleSmp(); public EatAppleForm() { InitializeComponent(); InitView(); m_EatAppleSmp.PutAction += PutActionMethod; m_EatAppleSmp.GetAction += GetActionMethod; } ////// 初始化GroupBox /// private void InitView() { this.gbBaba.Controls.Clear(); this.gbMama.Controls.Clear(); this.gbDage.Controls.Clear(); this.gbErdi.Controls.Clear(); this.gbSandi.Controls.Clear(); } ////// 启动线程 /// /// /// private void btnStart_Click(object sender, EventArgs e) { this.m_EatAppleSmp.BeginEat(); } ////// 放苹果事件 /// /// /// private void PutActionMethod(object sender, EventArgs e) { Productor p = sender as Productor; if (p != null) { if (p.Name == "Baba") { AddItemToGroupBox(this.gbBaba, this.lblBaba); } if (p.Name == "Mama") { AddItemToGroupBox(this.gbMama, this.lblMama); } } } ////// 吃苹果事件 /// /// /// public void GetActionMethod(object sender, EventArgs e) { Consumer c = sender as Consumer; if (c != null) { if (c.Name == "Dage") { AddItemToGroupBox(this.gbDage, this.lblDage); } if (c.Name == "Erdi") { AddItemToGroupBox(this.gbErdi, this.lblErdi); } if (c.Name == "Sandi") { AddItemToGroupBox(this.gbSandi, this.lblSandi); } } } ////// 往指定的GroupBox中添加对象 /// /// /// private void AddItemToGroupBox(GroupBox gbView,Label lbl) { gbView.Invoke(new Action(() => { PictureBox p = new PictureBox(); p.Width = 20; p.Height = 20; p.Dock = DockStyle.Left; p.Image = this.imgLst01.Images[0]; p.Margin = new Padding(2); gbView.Controls.Add(p); })); //显示个数 lbl.Invoke(new Action(() => { if (string.IsNullOrEmpty(lbl.Text)) { lbl.Text = "0"; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace DemoSharp.EatApple { ////// 消费者 /// public class Consumer { private string name; public string Name { get { return name; } set { name = value; } } private Dish dish; private int timelong; public EventHandler GetAction;//声明一个事件,当放苹果时触发该事件 public Consumer(string name, Dish dish, int timelong) { this.name = name; this.dish = dish; this.timelong = timelong; } public void run() { while (true) { bool flag= dish.Get(name); if (flag) { //如果取到苹果,则调用事件,并开始吃 if (GetAction != null) { GetAction(this, null); } try { Thread.Sleep(timelong);//吃苹果时间 } catch (ThreadInterruptedException) { } } else { break; } } } } } } lbl.Text = (int.Parse(lbl.Text) + 1).ToString(); })); } } }
登录后复制
Dish代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace DemoSharp.EatApple { ////// 盘子,属于中间类 /// public class Dish { private int f = 5;//表示盘子中还可以放几个苹果,最多只能放5个苹果 private int EnabledNum;//可放苹果总数 private int n = 0; //表示已经放了多少个苹果 private object objGet = new object(); private object objPut = new object(); ////// 构造函数,初始化Dish对象 /// /// 表示削够多少个苹果结束 public Dish(int num) { this.EnabledNum = num; } ////// 放苹果的方法 /// /// ///是否放成功 public bool Put(string name) { lock (this)//同步控制放苹果 { bool flag = false; while (f == 0)//苹果已满,线程等待 { try { System.Console.WriteLine(name + "正在等待放入苹果"); Monitor.Wait(this); } catch (Exception ex) { System.Console.WriteLine(name + "等不及了"); } } if (n /// 取苹果的方法 /// /// public bool Get(string name) { lock (this)//同步控制取苹果 { bool flag = false; while (f == 5) { try { System.Console.WriteLine(name + "等待取苹果"); Monitor.Wait(this); } catch (ThreadInterruptedException) { } } if (nEatAppleSmp代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace DemoSharp.EatApple { public class EatAppleSmp { public EventHandler PutAction;//声明一个事件,当放苹果时触发该事件 public EventHandler GetAction;//声明一个事件,当放苹果时触发该事件 ////// 开始吃苹果 /// public void BeginEat() { Thread th_mother, th_father, th_young, th_middle, th_old;//依次表示妈妈,爸爸,小弟,二弟,大哥 Dish dish = new Dish(30); Productor mother = new Productor("Mama", dish);//建立线程 mother.PutAction += PutActionMethod; Productor father = new Productor("Baba", dish); father.PutAction += PutActionMethod; Consumer old = new Consumer("Dage", dish, 1200); old.GetAction += GetActionMethod; Consumer middle = new Consumer("Erdi", dish, 1500); middle.GetAction += GetActionMethod; Consumer young = new Consumer("Sandi", dish, 1800); young.GetAction += GetActionMethod; th_mother = new Thread(new ThreadStart(mother.run)); th_mother.Name = "Mama"; th_father = new Thread(new ThreadStart(father.run)); th_father.Name = "Baba"; th_old = new Thread(new ThreadStart(old.run)); th_old.Name = "Dage"; th_middle = new Thread(new ThreadStart(middle.run)); th_middle.Name = "Erdi"; th_young = new Thread(new ThreadStart(young.run)); th_young.Name = "Sandi"; th_mother.Priority = ThreadPriority.Highest;//设置优先级 th_father.Priority = ThreadPriority.Normal; th_old.Priority = ThreadPriority.Lowest; th_middle.Priority = ThreadPriority.Normal; th_young.Priority = ThreadPriority.Highest; th_mother.Start(); th_father.Start(); th_old.Start(); th_middle.Start(); th_young.Start(); } private void GetActionMethod(object sender,EventArgs e) { if (GetAction != null) { GetAction(sender, e); } } private void PutActionMethod(object sender, EventArgs e) { if (PutAction != null) { PutAction(sender, e); } } }}登录后复制
界面类代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using DemoSharp.EatApple; namespace DemoSharp { ////// 页面类 /// public partial class EatAppleForm : Form { private EatAppleSmp m_EatAppleSmp = new EatAppleSmp(); public EatAppleForm() { InitializeComponent(); InitView(); m_EatAppleSmp.PutAction += PutActionMethod; m_EatAppleSmp.GetAction += GetActionMethod; } ////// 初始化GroupBox /// private void InitView() { this.gbBaba.Controls.Clear(); this.gbMama.Controls.Clear(); this.gbDage.Controls.Clear(); this.gbErdi.Controls.Clear(); this.gbSandi.Controls.Clear(); } ////// 启动线程 /// /// /// private void btnStart_Click(object sender, EventArgs e) { this.m_EatAppleSmp.BeginEat(); } ////// 放苹果事件 /// /// /// private void PutActionMethod(object sender, EventArgs e) { Productor p = sender as Productor; if (p != null) { if (p.Name == "Baba") { AddItemToGroupBox(this.gbBaba, this.lblBaba); } if (p.Name == "Mama") { AddItemToGroupBox(this.gbMama, this.lblMama); } } } ////// 吃苹果事件 /// /// /// public void GetActionMethod(object sender, EventArgs e) { Consumer c = sender as Consumer; if (c != null) { if (c.Name == "Dage") { AddItemToGroupBox(this.gbDage, this.lblDage); } if (c.Name == "Erdi") { AddItemToGroupBox(this.gbErdi, this.lblErdi); } if (c.Name == "Sandi") { AddItemToGroupBox(this.gbSandi, this.lblSandi); } } } ////// 往指定的GroupBox中添加对象 /// /// /// private void AddItemToGroupBox(GroupBox gbView,Label lbl) { gbView.Invoke(new Action(() => { PictureBox p = new PictureBox(); p.Width = 20; p.Height = 20; p.Dock = DockStyle.Left; p.Image = this.imgLst01.Images[0]; p.Margin = new Padding(2); gbView.Controls.Add(p); })); //显示个数 lbl.Invoke(new Action(() => { if (string.IsNullOrEmpty(lbl.Text)) { lbl.Text = "0"; } lbl.Text = (int.Parse(lbl.Text) + 1).ToString(); })); } } }登录后复制
更多C# 多线程经典示例 吃苹果相关文章请关注PHP中文网!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2551485.html