C# のリンゴを食べるマルチスレッドの典型的な例

高洛峰
リリース: 2017-02-08 14:30:41
オリジナル
1192 人が閲覧しました

この記事では主にマルチスレッド開発の古典的な例について説明します。この例を通じて、マルチスレッドについての理解を深めることができます。

サンプルの概要:

以下では、リンゴを食べることをシミュレートする例を使用して、C# でのマルチスレッドの実装方法を説明します。次のような状況を実現するためのプログラムを開発する必要があります。 家族に 3 人の子供がいて、両親はリンゴの皮をむいて皿に置き続けます。長男、二番目、三番目の子供はリンゴを皿から取り続けます。皿のサイズには制限があり、最大で 5 個までしか置くことができません。保護者が同時に皿にリンゴを置くことはできません。ママが優先されます。 3 人の子供がリンゴを取る場合、皿を空にすることはできません。また、3 人の子供が同時にリンゴを取ることはできません。3 番目の子供が最も優先され、最年長の子供が最も優先されます。最も年長の子が最も早く食べ、最も頻繁に摂取し、次に 2 番目に年長の子が続きます。

ナレッジポイントの関与:

スレッドはスレッドを作成および制御し、優先順位を設定し、そのステータスを取得します。

ロック マルチスレッド同期を実現する最も直接的な方法は、コードの一部を相互排他的なセグメントとして定義し、一度に 1 つのスレッドのみが実行を開始できるようにし、他のスレッドは待機する必要があることです。

イベント EventHandler は、変更を行うようにインターフェースに通知するイベントを宣言します

設計アイデア:

Productor は、リンゴの皮をむくために使用される生産者を表します。

Consumer は、リンゴを食べることに慣れている消費者を表します。

リンゴを置くために使用される皿プレートは、中間クラス

EatAppleSmpのBeginEat()メソッドとして機能します。これは、リンゴを食べ始めてスレッドを開始することを意味します

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

レンダリングは以下の通りです 【お父さんとお母さんがリンゴの皮をむく、子供たちはリンゴを食べる]:

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

バックグラウンド出力は次のとおりです:

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等待取苹果
ログイン後にコピー

プロダクト コードは次のとおりです:

  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;
                  }
              }
          }
      }
  }
ログイン後にコピー

コンシューマ コードは次のとおりです:

  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();
                            }));
                        }
                     }
                  }
ログイン後にコピー

ディッシュ コードは次のとおりです:

 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;
     }

     }
   } 
}
ログイン後にコピー

EatAppleSmp コード

 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);
             }
         }
     }
}
ログイン後にコピー

インターフェイス クラス コードは次のとおりです:

  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();
                            }));
                        }
                     }
                  }
ログイン後にコピー

その他の C# マルチスレッドの古典的な例 リンゴを食べることに関する記事については、PHP 中国語 Web サイトに注目してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート