AutoResetEvent信号锁 waitone set 执行一次线程退出 挺不爽的地方

Posted 蒙蒙大川

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AutoResetEvent信号锁 waitone set 执行一次线程退出 挺不爽的地方相关的知识,希望对你有一定的参考价值。

  下边有个 循环调用线程写奇偶数的程序

   class TheadTest
    {
        //定义一个Stream对象接收打开文件  
        private FileStream st;
        //构造方法  
        public TheadTest()
        {
        }
        public void Start()
        {
            //定义两个信号锁  
            AutoResetEvent ateA = new AutoResetEvent(false);
            AutoResetEvent ateB = new AutoResetEvent(false);
            //把信号锁加入到List中  
            List<AutoResetEvent> lst = new List<AutoResetEvent>();
            lst.Add(ateA);
            lst.Add(ateB);

            //定义带参数的输出偶数线程  
            Thread thrEven = new Thread(new ParameterizedThreadStart(OutPutEven));
            thrEven.Name = "偶数线程";
            //把两个信号锁传入线程  
            thrEven.Start(lst);

            //定义带参数的输出奇数线程  
            Thread thrOdd = new Thread(new ParameterizedThreadStart(OutPutOdd));
            thrOdd.Name = "极数线程";
            thrOdd.Start(lst);
        }

        private void OutPutEven(object lst)
        {
            AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
            AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];

            for (int i = 0; i < 100; i += 2)
            {
                //设置本线程为无信号  
                ateA.WaitOne();
                //输出  
                Console.WriteLine(i);
                //st = File.Open(@"C:/file.txt", FileMode.Open);      //用来测试同时访问文件系统的  
                //st.Close();  
                ateB.Set();  //设置输出奇数线程有信号  
                //Thread.Sleep(500);  
            }
        }
        private void OutPutOdd(object lst)
        {
            AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
            AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];
            //设置偶数线程先输出  
            ateA.Set();
            for (int i = 1; i < 100; i += 2)
            {
                //设置本线程为无信号  
                ateB.WaitOne();
                Console.WriteLine(10000);
                //st = File.Open(@"C:/file.txt", FileMode.Open);     //用来测试同时访问文件系统的  
                //st.Close();  
               ateA.Set(); //设置输出偶数线程有信号  
                //Thread.Sleep(500);  
           }
        }
    }

  

此时两个线程执行方法都在循环中没问题 ,程序是交互进行的,ateA 先执行,然后waitone ,等待ateB执行完发送set信号。

把其中一个循环去掉,

// for (int i = 1; i < 100; i += 2)
         //   {
                //设置本线程为无信号  
                ateB.WaitOne();
                Console.WriteLine(10000);
                //st = File.Open(@"C:/file.txt", FileMode.Open);     //用来测试同时访问文件系统的  
                //st.Close();  
               ateA.Set(); //设置输出偶数线程有信号  
                //Thread.Sleep(500);  
        //   }
运行结果:


 

就运行了三行拉倒了,而且是
ateA 运行了两次,
ateB运行了一次。  没有循环只运行了一次,线程就结束了。
ateA 的循环即使发送

ateB.set()信号也没用了,线程已经关闭了,运行一次就关闭了,当然应该考虑到线程启动关闭的运行效率,应该就是这么个规矩,线程启动要执行哪个程序,执行完毕,
、线程自动退出。实际运行中,这里有些理解上挺不爽的,不知道别人怎么样。
从理解的角度上讲,线程应该一直在那启动着,给予set信号,线程执行程序开始运行,执行完后等待下次set信号,而不应该退出。
所以要想用上这个知识点在程序中,还需要改进不少。这个问题上次处理上位机时碰到,当时已经知道这个问题,今天因为上边的写法中,参数和加了一个循环,
导致自己出现错觉了,以为这种写法就可以给信号执行,没信号不执行,执行完之后线程挂起而不是退出的功能

以上是关于AutoResetEvent信号锁 waitone set 执行一次线程退出 挺不爽的地方的主要内容,如果未能解决你的问题,请参考以下文章

C#中AutoResetEvent的waitOne()方法会影响到所有用户么?

多线程的AutoResetEvent

AutoResetEvent类的使用

线程同步之-旋转门AutoResetEvent

C# 线程间互相通信

线程的控制和线程池