zoukankan      html  css  js  c++  java
  • C#多线程处理之AutoResetEvent和ManualResetEvent

    有时我们在具体开发中,需要使把程序设计成多线程的逻辑。

    我们模拟这样一个场景:(C/S模式)

    1.客户端向服务端发送测量命令。

    2.服务端接受来自客户端的测量命令。

    3.服务端进行测量工作。

    4.服务端将测量结果,返回给客户端。

    以上4步是一个完整的交互过程。当我们要求服务端同时相应有多个客户端的测试命令时,就需要使用到多线程设计:针对每一个客户端建立一个线程执行以上4步,和其他客户端的线程互不干扰。

    多线程情况下,每个线程的执行顺序是并行的。但有时我们需要控制多个线程,使他们按特定的顺序执行,比如:当我们给上面的场景中的客服端加上‘优先级’的话。

    这里我们讲下如何使用AutoResetEvent和ManualResetEvent来控制多个线程的执行。

    1.简单的,我们创建3个线程,t1,t2,t3,依次打印出每个线程的ID,共打印10次。(现实中可能与不到这样的场景,但是这里用于演示如何控制多线程的)

    方案a:AutoResetEvent实现:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace ConsoleApplication14
    {
        class Program
        {
            static AutoResetEvent are1 = new AutoResetEvent(true);
            static AutoResetEvent are2 = new AutoResetEvent(false);
            static AutoResetEvent are3 = new AutoResetEvent(false);
    
    
            static void Main(string[] args)
            {              
    
                Thread t1 = new Thread(new ThreadStart(RunFun1));
                t1.Start();
                
                Thread t2 = new Thread(new ThreadStart(RunFun2));
                t2.Start();
                
                Thread t3 = new Thread(new ThreadStart(RunFun3));
                t3.Start(); 
               
                Console.Read();
            }
    
            static void RunFun1()
            {
                for (int i = 0; i < 10; i++)
                {
                    are1.WaitOne();
                    Console.WriteLine("The " + (i+1) + " times running:");
                    Console.WriteLine("Thread t1 ID:" + Thread.CurrentThread.ManagedThreadId);              
                    are2.Set();
                }
    
            }
    
            static void RunFun2()
            {
                for (int i = 0; i < 10; i++)
                {
                    are2.WaitOne();
                    Console.WriteLine("Thread t2 ID:" + Thread.CurrentThread.ManagedThreadId);               
                    are3.Set();                
                }
            }
    
            static void RunFun3()
            {
                for (int i = 0; i < 10; i++)
                {
                    are3.WaitOne();
                    Console.WriteLine("Thread t3 ID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine();
                    are1.Set();
                }
    
            }
    
          
        }
    }
    

    方案b:ManualResetEvent实现:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace ConsoleApplication15
    {
        class Program
        {
            static ManualResetEvent are1 = new ManualResetEvent(true);
            static ManualResetEvent are2 = new ManualResetEvent(false);
            static ManualResetEvent are3 = new ManualResetEvent(false);
    
    
            static void Main(string[] args)
            {
    
                Thread t1 = new Thread(new ThreadStart(RunFun1));
                t1.Start();
    
                Thread t2 = new Thread(new ThreadStart(RunFun2));
                t2.Start();
    
                Thread t3 = new Thread(new ThreadStart(RunFun3));
                t3.Start();
    
                Console.Read();
            }
    
            static void RunFun1()
            {
                for (int i = 0; i < 10; i++)
                {
                    are1.WaitOne();
                    Console.WriteLine("The " + (i + 1) + " times running:");
                    Console.WriteLine("Thread t1 ID:" + Thread.CurrentThread.ManagedThreadId);
                    ResetAll();
                    are2.Set();
                }
    
            }
    
            static void RunFun2()
            {
                for (int i = 0; i < 10; i++)
                {
                    are2.WaitOne();
                    Console.WriteLine("Thread t2 ID:" + Thread.CurrentThread.ManagedThreadId);
                    ResetAll();
                    are3.Set();
                }
            }
    
            static void RunFun3()
            {
                for (int i = 0; i < 10; i++)
                {
                    are3.WaitOne();
                    Console.WriteLine("Thread t3 ID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine();
                    ResetAll();
                    are1.Set();
                }
    
            }
    
            static void ResetAll()
            {
                are1.Reset();
                are2.Reset();
                are3.Reset();
            }
    
    
        }
    }
    

     AutoResetEvent与ManualResetEvent的使用方式基本一样,区别在与前者被Set后,只能允许一个线程,且只能通过一次。后者则可以允许多个线程,通过多次,直到手动Reset才不允许线程通过。

     上面代码的基本思想就是:为每个线程分配一个属于自己的信号量,每个线程执行前都要请求自己的信号量,同时执行完以后,要释放另外一个线程的信号量(既是:唤醒另外线程)。

    AuResetEvent变量每次被Set以后,WaitOne执行后,会自动恢复为非信号状态,不需要调用Reset。但是ManualResetEvent则需要。

  • 相关阅读:
    Linux每天一个命令:cat
    python3 str或bytes转换函数
    python3获取指定目录内容的详细信息
    python3 简单进度条代码
    CNN review
    Hive -- 原理篇
    leetcode 4. 寻找两个正序数组的中位数 (二分)
    leetcode 680 验证回文字符串II (贪心)
    leetcode 面试题03 数组中重复的数字
    机器学习--SVM篇
  • 原文地址:https://www.cnblogs.com/marksun/p/2997198.html
Copyright © 2011-2022 走看看