C\#다 중 스 레 드 고전 예제(사과 먹 기)

13370 단어 C#다 중 스 레 드
본 고 는 주로 다 중 스 레 드 개발 에서 전형 적 인 사례 를 서술 하고 본 사례 를 통 해 다 중 스 레 드 에 대한 이 해 를 강화 할 수 있다.
예제 요약:
다음은 사 과 를 먹 는 실례 를 모 의하여 C\#중 다 선정 의 실현 방법 을 설명 한다.한 가정 에 아이 가 셋 있 는데 아빠 와 엄 마 는 사 과 를 깎 아서 접시 에 넣 고 첫째,둘째,셋째 가 접시 에서 사 과 를 꺼 내 먹는다.접시 의 크기 가 제한 되 어 있 고 최대 5 개의 사과 만 넣 을 수 있 으 며 부모님 은 접시 에 사 과 를 동시에 넣 을 수 없 으 며 엄 마 는 우선권 을 가진다.세 아이 가 사 과 를 찾 을 때 접 시 를 비 워 서 는 안 되 고 세 사람 이 동시에 찾 을 수 없 으 며 셋째 우선권 이 가장 높 고 첫째 가 가장 낮다.첫째 가 가장 빨리 먹고,취 하 는 빈도 가 가장 높 으 며,둘째 가 그 다음 이다.
지식 포인트 관련:
  • 스 레 드 Thread 가 스 레 드 를 만 들 고 제어 하 며 우선 순 위 를 설정 하고 상 태 를 가 져 옵 니 다.
  • 잠 금 lock 은 다 중 스 레 드 동기 화 를 실현 하 는 가장 직접적인 방법 은 잠 금 을 추가 하 는 것 입 니 다.코드 를 상호 배척 세그먼트 로 정의 할 수 있 고 한 시간 동안 한 스 레 드 만 실행 할 수 있 으 며 다른 스 레 드 는 기 다 려 야 합 니 다.
  • 이벤트 EventHandler 는 하나의 사건 을 설명 하고 알림 인터페이스 에서 변경 하 는 데 사용 합 니 다
  • 디자인 아이디어:
  • Productor 는 생산 자 를 표시 하여 사 과 를 깎 는 데 사용한다.
  • Consumer 는 소비자 가 사 과 를 먹 는 데 쓰 인 다 고 밝 혔 다.
  • 접시,사 과 를 담 는 데 사용 되 며 중간 류
  • 로 한다.
  • 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
    {
     /// <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.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;
        }
       }
      }
     }
    }
    
    Dish 코드 는 다음 과 같 습 니 다.
    
    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();
       }));
      }
     }
    }
    
    이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!

    좋은 웹페이지 즐겨찾기