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则需要。

 

你可能感兴趣的:(event)