首页 > 代码库 > AutoResetEvent详解

AutoResetEvent详解

在MSDN中,它的解释为:通知正在等待的线程已发生事件。无法继承此类(密封类)。

AutoResetEvent 允许线程通过发信号进行相互通信,例如发Set信号,让正在WaitOne等待信号着的线程开启继续执行。通常,此通信涉及线程需要独立访问的资源。

线程通过调用 AutoResetEvent 上的WaitOne来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set发出资源可用的信号。

调用 Set 向 AutoResetEvent 发信号以释放等待线程,这里释放的是有WaitOne等待着的随机的某一个线程 ,而不是所有有WaitOne等待信号的线程,此时AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待(没有一个线程有WaitOne等待信号),则状态将无限期地保持为终止状态。

 

它可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为终止状态,则为 true;否则为 false

 

示例代码:

实现类源码:

class AutoResetEventTest    {        private AutoResetEvent are;        public AutoResetEventTest()        {            this.are = new AutoResetEvent(false);        }        /// <summary>        /// 放行等待的线程        /// </summary>        public void Set()        {            this.are.Set();        }        /// <summary>        /// 暂停正在等待的线程        /// </summary>        public void Reset()        {            this.are.Reset();        }        /// <summary>        /// 启动N个线程,可以手动传入参数指定启动几个线程        /// </summary>        /// <param name="threadNumber"></param>        public void CreateThreads(int threadNumber)        {            Thread[] threads = new Thread[threadNumber];            for (int i = 0; i < threadNumber; i++)            {                threads[i] = new Thread(new ThreadStart(Run));                threads[i].Start();            }        }        /// <summary>        /// 正在等待着的线程,该线程打印出线程ID        /// </summary>        private void Run()        {            string threadId = string.Empty;            try            {                while (true)                {                    // 阻塞当前线程                    this.are.WaitOne();                    threadId = Thread.CurrentThread.ManagedThreadId.ToString();                    Console.WriteLine("Run---Thread(" + threadId + ") is running...");                    Thread.Sleep(3000);                }            }            catch (Exception ex)//异常处理            {                Console.WriteLine("Run---Thread(" + threadId + ") Error happend!:" + ex.Message.ToString());            }        }    }

 

主函数源码:

在控制台界面上输入run会看到某个等待着的线程被开启:

    class Program    {        static void Main(string[] args)        {            Console.WriteLine("**********************************");            Console.WriteLine("请输入\"run\"开启正在等待着的线程...");            Console.WriteLine("********************************\r\n");            AutoResetEventTest test = new AutoResetEventTest();            test.CreateThreads(10);            while (true)            {                string input = Console.ReadLine();                if (input.Trim().ToLower() == "run")                {                    Console.WriteLine("WaitOne等待着的某个线程开启运行...");                    test.Set();                }            }        }    }

 

运行结果:

当输入一次run时,显示如下:

由于初始化AutoResetEvent 事件为false,则该事件处于非终止状态,故所有等待着的线程在没有Set信号到来时,都将暂停运行,当输入一次run,调用AutoResetEvent 的Set方法,将会随机开启某一个正在等待着的线程,当该等待着的线程被释放,则AutoResetEvent 自动的变为非终止状态,其余的等待线程想要开启就必须等待再一次Set信号。

 

当输入多次run时,显示结果如下:

每输入一次run都会调用AutoResetEvent 事件的Set方法,将会随机开启某一个正在等待着的线程,当这个线程被释放后,则AutoResetEvent  事件会自动的置为非终止状态,那么刚刚被开启的线程将会再次等待,直到等待下一次Set信号将它开启。

假如我们初始化将AutoResetEvent 事件设置为true,则在控制台下会看到如下结果:

这是因为初始化将AutoResetEvent 事件设置为true,则它会处于终止状态,那么会初次开启某个线程,当这个等待着的线程被释放时,则会自动将AutoResetEvent 设置成非终止状态,直到有Set信号给某个等待着的线程,才会开启这个等待着的线程。

 

如下:

再一次输入run,

 

调用AutoResetEvent  的Set方法,将会随机的开启某一个正在等待着的线程,线程释放完毕后会自动将AutoResetEvent 置为非终止状态,所以每当run一次只能看到一次随机等待的线程在跑

 

 

AutoResetEvent详解