博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AutoResetEvent和ManualResetEvent
阅读量:5988 次
发布时间:2019-06-20

本文共 3085 字,大约阅读时间需要 10 分钟。

  首先说说线程的终止状态和非终止状态。AutoResetEvent和ManualResetEvent的构造函数中,都有bool变量来指明线程的终止状态和非终止状态。true表示终止状态,false表示非终止状态。看代码片段1:

 

代码片段1:

        AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

 

        private void BT_Temp_Click(object sender, RoutedEventArgs e)

        {

            Thread t1 = new Thread(this.Thread1Foo);

            t1.Start();

            Thread.Sleep(3000);

            _autoResetEvent.Set();

        }

 

        void Thread1Foo()

        {

            _autoResetEvent.WaitOne();

            MessageBox.Show("t1 end");

        }

    这段代码的执行结果,就是3秒钟过后,弹出“t1 end”。

    而如果把:

    AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

    改为:

    AutoResetEvent _autoResetEvent = new AutoResetEvent(true);

    则“t1 end”将会立刻弹出。

    也就是说,在终止状态中,_autoResetEvent.WaitOne()是不会起到阻滞工作线程的作用的。(PS:ManualResetEvent也同样)

 

二:AutoResetEvent和ManualResetEvent的区别

    接下来,再来看看AutoResetEvent和ManualResetEvent的区别。我们看代码段2和代码段3:

 

代码段2:

        AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

        private void BT_Temp_Click(object sender, RoutedEventArgs e)

        {

            Thread t1 = new Thread(this.Thread1Foo);

            t1.Start();

            Thread t2 = new Thread(this.Thread2Foo);

            t2.Start();

            Thread.Sleep(3000);

            _autoResetEvent.Set();

        }

 

        void Thread1Foo()

        {

            _autoResetEvent.WaitOne();

            MessageBox.Show("t1 end");

        }

 

        void Thread2Foo()

        {

            _autoResetEvent.WaitOne();

            MessageBox.Show("t2 end");

        }

    该段代码运行的效果是,过3秒后,要么弹出“t1 end”,要么弹出“t2 end”,不会两个都弹出。也就是说,其中一个进行将会结束,而另一个进程永远不会结束。

 

代码段3:

        ManualResetEvent _menuRestEvent = new ManualResetEvent(false);

 

        private void BT_Temp_Click(object sender, RoutedEventArgs e)

        {

            Thread t1 = new Thread(this.Thread1Foo);

            t1.Start();

            Thread t2 = new Thread(this.Thread2Foo);

            t2.Start();

            Thread.Sleep(3000);

            _menuRestEvent.Set();

        }

 

        void Thread1Foo()

        {

            _menuRestEvent.WaitOne();

            MessageBox.Show("t1 end");

        }

 

        void Thread2Foo()

        {

            _menuRestEvent.WaitOne();

            MessageBox.Show("t2 end");

        }

    该段代码运行的效果是,过3秒后,“t1 end”和“t2 end”,两个都被弹出。也就是说,两个进程都结束了。

    这个特性就是说,AutoResetEvent只会给一个线程发送信号,而不会给多个线程发送信号。在我们需要同步多个线程的时候,就只能采用ManualResetEvent了。至于深层次的原因是,AutoResetEvent在set()之后,会将线程状态自动置为false,而ManualResetEvent在Set()后,线程的状态就变为true了,必须手动ReSet()之后,才会重新将线程置为false。这也就是为什么他们的名字一个为Auto,一个为Manual的原因。为了更加充分的验证ManualResetEvent的这点特性,我们再来看代码片段4

 

代码片段4:

    ManualResetEvent _menuRestEvent = new ManualResetEvent(false);

 

        private void BT_Temp_Click(object sender, RoutedEventArgs e)

        {

            Thread t1 = new Thread(this.Thread1Foo);

            t1.Start();

            Thread t2 = new Thread(this.Thread2Foo);

            t2.Start();

            Thread.Sleep(3000);

            _menuRestEvent.Set();

            //_menuRestEvent.Reset();            

        }

 

        void Thread1Foo()

        {

            _menuRestEvent.WaitOne();

            MessageBox.Show("t1 step1 end");

            //睡1S,用于等待主线程_menuRestEvent.Reset();

            Thread.Sleep(1000);

            _menuRestEvent.WaitOne();

            MessageBox.Show("t1 step2 end");

        }

 

        void Thread2Foo()

        {

            _menuRestEvent.WaitOne();

            MessageBox.Show("t2 step1 end");

            //睡1S,用于等待主线程_menuRestEvent.Reset();

            Thread.Sleep(1000);

            _menuRestEvent.WaitOne();

            MessageBox.Show("t2 step2 end");

        }

    在代码片段4中,我们对//_menuRestEvent.Reset()进行了注释,也就是说, _menuRestEvent.Set()后,线程的状态就是true状态的,程序运行的结果是"t1 step1 end"、"t1 step2 end"、"t1 step2 end"、"t2 step2 end"在3秒之后全部弹出。

    而如果我们将//_menuRestEvent.Reset()的注释去掉,会发现"t1 step2 end"和"t2 step2 end"永远不会弹出。除非我们在主线程中再次对_menuRestEvent进行Set()。

转载于:https://www.cnblogs.com/kevinGao/archive/2012/04/13/2482119.html

你可能感兴趣的文章
Cocos Creator 鼠标事件
查看>>
类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
查看>>
neo4j图数据库入门
查看>>
内核定时器timer_list
查看>>
VirtualBox - NAT虚拟机访问外网 + Host-Only物理主机虚拟机互访
查看>>
99. Recover Binary Search Tree
查看>>
appium+python自动化32-android_uiautomator定位进阶版
查看>>
《Java 多线程编程核心技术》- 笔记
查看>>
劣质代码评析——《写给大家看的C语言书(第2版)》附录B之21点程序(六)...
查看>>
ashx的学习
查看>>
Installing ODIConsole application using weblogic server
查看>>
hp警告Creating default object from empty value 问题的解决方法
查看>>
C#游戏开发中快速的游戏循环
查看>>
如何高效快捷检索得到核心文献?
查看>>
使用MVC写模式jsp连接到数据库操作
查看>>
模拟电路创新设计
查看>>
win10安装blueCFD
查看>>
C# 计算两个字符串的相似度
查看>>
linux 遇见错误Could not get lock /var/lib/dpkg/lock
查看>>
MySQLdump常用命令
查看>>