栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

C#使用ManualResetEvent和AutoResetEvent处理线程通信

Java 更新时间:发布时间: 百科书网 趣学号
示例

两个线程交替输出“1 a 2 b 3 c 4 d 5 .....”

代码
    //利用ManualResetEvent和AutoResetEvent交替输出“1 a 2 b 3 c 4 d 5 .....”

    //ManualResetEvent和AutoResetEvent不同点:
    //AutoResetEvent 收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne 
    //ManualResetEvent 收到 Set 后,所有处理 WaitOne 状态线程均继续执行
    //AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();

    //在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,
    //Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。
    //如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne() 每次只允许一个线程进入, 
    //当某个线程得到信号后, AutoResetEvent会自动又将信号置为不发送状态, 则其他调用WaitOne的线程只有继续等待.
    //也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set() 方法后, 
    //其他调用WaitOne的线程获得信号得以继续执行, 而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset() 方法, 
    //则ManualResetEvent将一直保持有信号状态, ManualResetEvent也就可以同时唤醒多个线程继续执行。

    //本质上AutoResetEvent.Set() 方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();
    //因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
    class Program
    {
        private static List _listManual = new List();
        private static List _listAuto = new List();
        private static List _listNumber = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        private static List _listLetter = new List() { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
        //private static List _listUpperLetter = new List() { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
        static void Main(string[] args)
        {
            #region ManualResetEvent

            _listManual.Add(new ManualResetEvent(false));//用于控制_listNumber的信号灯
            _listManual.Add(new ManualResetEvent(false));//用于控制_listLetter的信号灯

            Task.Run(() =>
            {
                _listNumber.ForEach(c =>
                {
                    _listManual[0].WaitOne();
                    Console.WriteLine(c);
                    _listManual[0].Reset();
                    _listManual[1].Set();
                });
            });

            Task.Run(() =>
            {
                _listLetter.ForEach(c =>
                {
                    _listManual[1].WaitOne();
                    Console.WriteLine(c);
                    _listManual[0].Set();
                    _listManual[1].Reset();
                });
            });

            _listManual[0].Set();

            Console.ReadKey();

            #endregion

            #region AutoResetEvent

            _listAuto.Add(new AutoResetEvent(false));//用于控制_listNumber的信号灯
            _listAuto.Add(new AutoResetEvent(false));//用于控制_listLetter的信号灯

            Task.Run(() =>
            {
                _listNumber.ForEach(c =>
                {
                    _listAuto[0].WaitOne();
                    Console.WriteLine(c);
                    _listAuto[1].Set();
                    //不需要ReSet,因为AutoResetEvent在某个wait的线程得到信号后会自动变为ReSet,WaitOne每次只允许一个线程进入
                });
            });

            Task.Run(() =>
            {
                _listLetter.ForEach(c =>
                {
                    _listAuto[1].WaitOne();
                    Console.WriteLine(c);
                    _listAuto[0].Set();
                });
            });

            _listAuto[0].Set();

            Console.ReadKey();

            #endregion
        }
    }

    //Reset() //红灯
    //Set() //绿灯
    //WaitOne() // 等待信号
输出

 

 

 

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/957140.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号