Home > Backend Development > C#.Net Tutorial > C# multi-threading classic example eating apples

C# multi-threading classic example eating apples

高洛峰
Release: 2017-02-08 14:30:41
Original
1203 people have browsed it

This article mainly talks about classic examples in multi-threading development. Through this example, you can deepen your understanding of multi-threading.

Example overview:

The following uses an example of simulating eating an apple to illustrate the implementation method of multi-threading in C#. It is required to develop a program to realize the following situation: There are three children in a family. The parents keep peeling apples and put them on the plate. The eldest, second and third eldest child keep taking apples from the plate to eat. The size of the plate is limited, and only 5 apples can be placed at most. Parents cannot put apples on the plate at the same time. Mother has priority. When three children take apples, the plates cannot be empty, and the three children cannot take them at the same time. The third child has the highest priority and the eldest child has the lowest. The oldest one eats the fastest and takes the most frequently, followed by the second oldest.

Related to knowledge points:

Thread Thread creates and controls a thread, sets its priority and obtains its status.

Lock lock The most direct way to achieve multi-thread synchronization is to lock. It can define a piece of code as a mutually exclusive segment, allowing only one thread to enter execution at a time, while other threads must wait.

Event EventHandler declares an event to notify the interface to make changes

Design idea:

Productor represents the producer and is used to peel apples.

Consumer represents the consumer, used to eat apples.

Dish plate, used to hold apples, used as the BeginEat() method of the intermediate class

EatAppleSmp, which means to start eating apples and start the thread

------ -------------------------------------------------- ----------------------------------------

The renderings are as follows [Mom and dad peel apples, children eat apples]:

C# 多线程经典示例 吃苹果

The background output is as follows:

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等待取苹果
Copy after login

Productor code is as follows:

  using System; 
  using System.Collections.Generic; 
  using System.Linq; 
  using System.Text; 
  using System.Threading; 
   
  namespace DemoSharp.EatApple 
  { 
      /// <summary>
      /// 生产者
      /// </summary>
      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;
                  }
              }
          }
      }
  }
Copy after login

Consumer code As follows:

  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 
 { 
     /// <summary> 
     /// 页面类 
    /// </summary> 
     public partial class EatAppleForm : Form 
     { 
        private EatAppleSmp m_EatAppleSmp = new EatAppleSmp(); 
  
        public EatAppleForm() 
        { 
            InitializeComponent(); 
             InitView(); 
             m_EatAppleSmp.PutAction += PutActionMethod; 
             m_EatAppleSmp.GetAction += GetActionMethod; 
        } 
 
         /// <summary>
         /// 初始化GroupBox 
         /// </summary> 
         private void InitView() 
         { 
             this.gbBaba.Controls.Clear(); 
             this.gbMama.Controls.Clear(); 
              this.gbDage.Controls.Clear(); 
             this.gbErdi.Controls.Clear(); 
             this.gbSandi.Controls.Clear(); 
        } 
  
         /// <summary>
          /// 启动线程
            /// </summary> 
             /// <param name="sender"></param> 
           /// <param name="e"></param> 
           private void btnStart_Click(object sender, EventArgs e)
             { 
                this.m_EatAppleSmp.BeginEat(); 
             } 
     
            /// <summary> 
            /// 放苹果事件 
            /// </summary>
             /// <param name="sender"></param> 
            /// <param name="e"></param>
              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); 
                       } 
                 } 
               } 
        
               /// <summary> 
               /// 吃苹果事件 
               /// </summary> 
             /// <param name="sender"></param> 
               /// <param name="e"></param> 
               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); 
                             } 
                           } 
                      } 
                
                      /// <summary> 
                     /// 往指定的GroupBox中添加对象
                      /// </summary>
                        /// <param name="gbView"></param>
                        /// <param name="lbl"></param>
                       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 
 { 
     /// <summary>
     /// 消费者
        /// </summary>
     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();
                            }));
                        }
                     }
                  }
Copy after login

Dish code is as follows:

 using System; 
 using System.Collections.Generic; 
 using System.Linq; 
 using System.Text; 
 using System.Threading; 
  
 namespace DemoSharp.EatApple 
 { 
     /// <summary>
     /// 盘子,属于中间类
     /// </summary>
     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();
 
         /// <summary>
         /// 构造函数,初始化Dish对象
         /// </summary>
         /// <param name="num">表示削够多少个苹果结束</param>
         public Dish(int num)
         {
             this.EnabledNum = num;
         }
         /// <summary>
         /// 放苹果的方法
         /// </summary>
         /// <param name="name"></param>
          ///<returns>是否放成功</returns>
         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 < EnabledNum)
  {
   f = f - 1;//削完一个苹果放一次
     n = n + 1;
 System.Console.WriteLine(name + "放1个苹果");
  flag = true;
      }
  Monitor.PulseAll(this);
        return flag;
      }
      }

       /// <summary>
       /// 取苹果的方法
        /// </summary>
        /// <param name="name"></param>
       public bool Get(string name)
       {
         lock (this)//同步控制取苹果
           {
             bool flag = false;
               while (f == 5)
              {
                  try
                  {
                       System.Console.WriteLine(name + "等待取苹果");
                      Monitor.Wait(this);
                    }
                    catch (ThreadInterruptedException) { }
   }
      if (n <= EnabledNum)
      {
             f = f + 1;
          System.Console.WriteLine(name + "取苹果吃...");
             flag = true;
           }
              Monitor.PulseAll(this);
            return flag;
     }

     }
   } 
}
Copy after login

EatAppleSmp code is as follows:

 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;//声明一个事件,当放苹果时触发该事件

         /// <summary>
         /// 开始吃苹果
        /// </summary>
         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);
             }
         }
     }
}
Copy after login

Interface class code is as follows:

  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 
 { 
     /// <summary> 
     /// 页面类 
    /// </summary> 
     public partial class EatAppleForm : Form 
     { 
        private EatAppleSmp m_EatAppleSmp = new EatAppleSmp(); 
  
        public EatAppleForm() 
        { 
            InitializeComponent(); 
             InitView(); 
             m_EatAppleSmp.PutAction += PutActionMethod; 
             m_EatAppleSmp.GetAction += GetActionMethod; 
        } 
 
         /// <summary>
         /// 初始化GroupBox 
         /// </summary> 
         private void InitView() 
         { 
             this.gbBaba.Controls.Clear(); 
             this.gbMama.Controls.Clear(); 
              this.gbDage.Controls.Clear(); 
             this.gbErdi.Controls.Clear(); 
             this.gbSandi.Controls.Clear(); 
        } 
  
         /// <summary>
          /// 启动线程
            /// </summary> 
             /// <param name="sender"></param> 
           /// <param name="e"></param> 
           private void btnStart_Click(object sender, EventArgs e)
             { 
                this.m_EatAppleSmp.BeginEat(); 
             } 
     
            /// <summary> 
            /// 放苹果事件 
            /// </summary>
             /// <param name="sender"></param> 
            /// <param name="e"></param>
              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); 
                       } 
                 } 
               } 
        
               /// <summary> 
               /// 吃苹果事件 
               /// </summary> 
             /// <param name="sender"></param> 
               /// <param name="e"></param> 
               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); 
                             } 
                           } 
                      } 
                
                      /// <summary> 
                     /// 往指定的GroupBox中添加对象
                      /// </summary>
                        /// <param name="gbView"></param>
                        /// <param name="lbl"></param>
                       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();
                            }));
                        }
                     }
                  }
Copy after login

More C# multi-threading classic examples For articles related to eating apples, please pay attention to the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template