Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#线程:使用监视器。等待、锁定和脉冲锁定_C#_Multithreading - Fatal编程技术网

C#线程:使用监视器。等待、锁定和脉冲锁定

C#线程:使用监视器。等待、锁定和脉冲锁定,c#,multithreading,C#,Multithreading,我不熟悉CSharp和线程 为了熟悉Monitor.Wait、Monitor.lock和Monitor.pulsell,我构建了下面描述的场景 “不同球队共用一个足球场进行练习。在任何时候,只有一支球队可以使用该场地进行练习。一支球队可以使用该场地进行30分钟的练习。当时间达到25分钟时,应向其他球队发出信号,表示5分钟后该场地将腾空。当地面潮湿时(enum有三个值:自由、分配、湿)不允许任何团队锁定地面,所有团队应等待10分钟” 老实说,我不知道如何将描述转化为实际编码。根据我的理解,我设

我不熟悉CSharp和线程

为了熟悉Monitor.Wait、Monitor.lock和Monitor.pulsell,我构建了下面描述的场景

“不同球队共用一个足球场进行练习。在任何时候,只有一支球队可以使用该场地进行练习。一支球队可以使用该场地进行30分钟的练习。当时间达到25分钟时,应向其他球队发出信号,表示5分钟后该场地将腾空。当地面潮湿时(enum有三个值:自由、分配、湿)不允许任何团队锁定地面,所有团队应等待10分钟”

老实说,我不知道如何将描述转化为实际编码。根据我的理解,我设计了大纲

namespace ThreadingSimulation
 {

  // A Random Activity can be picked up from this enum by a team

         public enum RandomGroundStatus
         {
             free,
             allotted,
             Wet          
         }

class FootBallGround
{

    public void Playing(object obj)
    {
      // Here the name of the team which is using the  ground will be printed
      // Once the time is reached to 25 minnutes the active thread acquired
      // the lock will signal  other threads    

    }

   public void GroundCleaningInProgress(object obj)
   {

      // Ground cleaning is in progress all of you
      // wait for 10 minutes

   }

}    




 class Team
   {
     string teamName;  

      static void Main()
      {

        //select random value for GrandStatus from enum

       // if the ground is wet no team is allowed to get the
       // ground for 10 minutes  

        //if the ground is free "Team A" locks the ground

        // otherwise "Team B" locks the ground

      }

   }

}

在这里,我不知道如何应用锁和信号。请帮帮我。

锁定和多线程应用程序要始终记住的重要一点是,只有当访问锁定资源的所有代码都遵循相同的规则时,锁定才有效,即如果一个线程可以锁定资源,那么所有其他线程都可以访问相同的资源资源应该在访问该资源之前使用锁

监视和锁定

lock
关键字是
Monitor
类的方便包装。这意味着
lock(obj)
Monitor.Enter(obj)
相同(尽管
Monitor
增加了一个功能,如果无法获得对象的锁,则在一段时间后超时)

脉冲事件和线程

当多个线程正在等待获得对某个资源的锁定时,可以通过代码在所有者线程使用资源完成时发出信号。这称为信号发送或脉冲发送,可以通过
Monitor.Pulse
Monitor.pulsell
ManualResetEvent.Set
甚至
AutoResetEvent.Set
来完成>

足球范例 因此,下面的足球示例将编码为包含线程锁定,如下所示:

 namespace ThreadingSimulation
 {

   // A Random Activity can be picked up from this enum by a team

    public enum RandomGroundStatus
    {
        Free,
        Allotted,
        Wet          
    }

 class FootBallGround
 {
     private Team _currentTeam;

     // Set the initial state to true so that the first thread that 
     // tries to get the lock will succeed
     private ManualResetEvent _groundsLock = new ManualResetEvent(true);

     public bool Playing(Team obj)
     {
       // Here the name of the team which is using the  ground will be printed
       // Once the time is reached to 25 minutes the active thread the lock will
       // signal other threads    
       if (!_groundsLock.WaitOne(10))
         return false;

       _currentTeam = obj;

       // Reset the event handle so that no other thread can come into this method
       _groundsLock.Reset();    

       // Now we start a separate thread to "timeout" this team's lock 
       // on the football grounds after 25 minutes
       ThreadPool.QueueUserWorkItem(WaitForTimeout(25));                  
     }

    public void GroundCleaningInProgress(object obj)
    {

       // Ground cleaning is in progress all of you wait for 10 minutes

    }

    private void WaitForTimeout(object state)
    {
         int timeout = (int)state;

         // convert the number we specified into a value equivalent in minutes
         int milliseconds = timeout * 1000;
         int minutes = milliseconds * 60;

         // wait for the timeout specified 
         Thread.Sleep(minutes);

         // now we can set the lock so another team can play
         _groundsLock.Set();
     }
 }    

 class Team
  {
      string teamName;  
      FootBallGround _ground;

       public Team(string teamName, FootBallGround ground)
       {
          this.teamName = teamName;
          this._ground = ground;      
       }

       public bool PlayGame()
       {
            // this method returns true if the team has acquired the lock to the grounds
            // otherwise it returns false and allows other teams to access the grounds
            if (!_ground.Playing(this))
               return false;
            else
               return true;
       }
  }


  static void Main()
  {
         Team teamA = new Team();
         Team teamB = new Team();

         // select random value for GrandStatus from enum
         RandomGroundStatus status = <Generate_Random_Status>;

         // if the ground is wet no team is allowed to get the
         // ground for 10 minutes.
         if (status == RandomGroundStatus.Wet)
            ThreadPool.QueueUserWorkItem(WaitForDryGround);
         else
         {
             // if the ground is free, "Team A" locks the ground
             // otherwise "Team B" locks the ground

             if (status == RandomGroundStatus.Free)
             {
               if (!teamA.PlayGame())
                  teamB.PlayGame();
             }
          }
    }
命名空间线程模拟
{
//团队可以从此枚举中选取随机活动
公共枚举状态
{
自由的
分配给,
潮湿的
}
班级足球场
{
私人团队(私人团队);;
//将初始状态设置为true,以便第一个线程
//尝试获取锁将成功
专用手动复位事件\u地面锁定=新手动复位事件(真);
公共足球赛(obj队)
{
//这里将打印使用场地的团队的名称
//一旦时间达到25分钟,活动线程将锁定
//向其他线程发送信号
如果(!_groundsLock.WaitOne(10))
返回false;
_currentTeam=obj;
//重置事件句柄,以便没有其他线程进入此方法
_groundsLock.Reset();
//现在我们启动一个单独的线程来“超时”这个团队的锁
//25分钟后在足球场上
QueueUserWorkItem(WaitForTimeout(25));
}
公共空地清理进度(对象obj)
{
//地面清理正在进行,请大家等待10分钟
}
私有void WaitForTimeout(对象状态)
{
int超时=(int)状态;
//将我们指定的数字转换为分钟内的等效值
整数毫秒=超时*1000;
整数分钟=毫秒*60;
//等待指定的超时
睡眠(分钟);
//现在我们可以设置锁,以便另一支球队可以比赛
_groundsLock.Set();
}
}    
班队
{
字符串组名;
足球场;;
公共队(队名、足球场)
{
this.teamName=团队名称;
这个。_地面=地面;
}
公共布尔游戏()
{
//如果团队已获得地面锁,则此方法返回true
//否则返回false并允许其他团队进入场地
如果(!_地面。播放(此))
返回false;
其他的
返回true;
}
}
静态void Main()
{
团队A=新团队();
团队B=新团队();
//从枚举中为大状态选择随机值
随机状态状态=;
//如果地面是湿的,任何队伍都不允许进入
//地面停留10分钟。
如果(状态==RandomGroundStatus.Wet)
ThreadPool.QueueUserWorkItem(WaitForDryGround);
其他的
{
//如果地面空闲,“A队”锁定地面
//否则“B队”将锁定地面
if(status==RandomGroundStatus.Free)
{
如果(!teamA.PlayGame())
teamB.PlayGame();
}
}
}
}

**注释**

  • 使用
    ManualResetEvent
    而不是
    lock
    Monitor
    ,因为我们希望直接控制锁的状态何时脉冲,以使其他线程能够玩足球游戏

  • 将对
    足球场
    的参考传递给每个
    团队
    ,因为每个团队将在特定的足球场上比赛,并且每个足球场可能被另一个团队占用

  • 传递对当前在
    足球场上比赛的球队的引用,因为一次只能有一支球队在球场上比赛

  • 使用
    ThreadPool.QueueUserWorkItem
    ,因为它在创建简单线程方面比我们手动创建线程更有效。理想情况下,我们也可以使用
    计时器
    实例


事实上,您的场景并没有很大程度地映射到一个
-但我们无论如何都会尝试;-p

我已经
using System;
using System.Threading;
interface IGroundUser
{
    bool Invoke(); // do your stuff; return true to wake up *everyone*
                   // afterwards, else false
}
class Team : IGroundUser
{
    private readonly string name;
    public Team(string name) { this.name = name; }
    public override string ToString() { return name; }
    public bool Invoke()
    {
        Console.WriteLine(name + ": playing...");
        Thread.Sleep(25 * 250);
        Console.WriteLine(name + ": leaving...");
        return false;
    }
}
class Cleaner : IGroundUser
{
    public override string ToString() {return "cleaner";}
    public bool Invoke()
    {
        Console.WriteLine("cleaning in progress");
        Thread.Sleep(10 * 250);
        Console.WriteLine("cleaning complete");
        return true;
    }
}
class FootBallGround
{
    static void Main()
    {
        var ground = new FootBallGround();
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team A")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team B")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Cleaner()); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team C")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team D")); });
        ThreadPool.QueueUserWorkItem(delegate { ground.UseGrounds(new Team("Team E")); });
        Console.ReadLine();

    }
    bool busy;
    private readonly object syncLock = new object();
    public void UseGrounds(IGroundUser newUser)
    {
        // validate outside of lock
        if (newUser == null) throw new ArgumentNullException("newUser");
        // only need the lock when **changing** state
        lock (syncLock)
        {
            while (busy)
            {
                Console.WriteLine(newUser + ": grounds are busy; waiting...");
                Monitor.Wait(syncLock);
                Console.WriteLine(newUser + ": got nudged");
            }
            busy = true; // we've got it!
        }
        // do this outside the lock, allowing other users to queue
        // waiting for it to be free
        bool wakeAll = newUser.Invoke();

        // exit the game
        lock (syncLock)
        {
            busy = false;
            // wake up somebody (or everyone with PulseAll)
            if (wakeAll) Monitor.PulseAll(syncLock);
            else Monitor.Pulse(syncLock);
        }
    }    
}