为了账号安全,请及时绑定邮箱和手机立即绑定

多线程中的ManualResetEvent

标签:
前端工具

先来看一下简单的多线程控制台程序:


using System;
using System.Threading;

namespace ManualResetEventStudy
{

    class ThreadClass
    {
        static void t1()
        {
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("t1的x:" + x);
            }
        }

        static void t2()
        {
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("t2的x:" + x);
            }
        }

        static void Main(string[] args)
        {
            Thread thrd1 = new Thread(t1);
            thrd1.Start();

            Thread thrd2 = new Thread(t2);
            thrd2.Start();


            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("主线程中的x:" + x);
            }

            Console.Read();
        }       
    }
}

 入口方法Main里,创建了二个线程,分别调用方法t1与t2,再加上主线程本身,一并有三个线程,运行后,三个线程都在计数输出,结果类似如下:

t2的x:1
t1的x:1
主线程中的x:1
t2的x:2
t1的x:2
主线程中的x:2
t2的x:3
t1的x:3
主线程中的x:3
t2的x:4
t1的x:4
主线程中的x:4
t2的x:5
t1的x:5
主线程中的x:5

 

三个线程的顺序,在这段代码中我们是无法控制的,天知道谁先开始/谁先结束,反正都是"并行"处理,完全看CPU当时的心情  :)

问题:如果需求有变化,比如要求在主线程执行到某个特定的位置(或时间点)时,才让其它线程开始介入,该怎么做呢?(这种情况实际中很常见,比如某一项计算的入口参数依赖于另一项计算的结果,再比如我们计算月工资前,得先统计出员工当月考勤情况)

System.Threading命名空间下有一个ManualResetEvent类,可以做到这一点:

using System;
using System.Threading;

namespace ManualResetEventStudy
{

    class ThreadClass
    {       

        static ManualResetEvent mre = new ManualResetEvent(false);

        static void t1()
        {
            mre.WaitOne(1000);//等待1秒后,自行启动
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("t1的x:" + x);
            }
        }

        static void t2()
        {
            mre.WaitOne();//一直等待下去,直到有"人"调用mre.set()发出信号为止
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("t2的x:" + x);
            }
        }

        static void Main(string[] args)
        {
            Thread thrd1 = new Thread(t1);
            thrd1.Start();

            Thread thrd2 = new Thread(t2);
            thrd2.Start();


            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(500);
                Console.WriteLine("主线程中的x:" + x);

                if (x == 3) 
                {
                    mre.Set();//通知所有等待的线程:“同志们,可以动啦”:)
                }
            }

            Console.Read();
        }        

    }
}


 t1方法中,我们用 mre.WaitOne(1000);让调用该方法的线程先等候1秒,t2方法中,我们用mre.WaitOne()无限等候,然后主线程中计数到3的时候,手动调用mre.Set()方法唤醒所有等候中的线程,运行结果类似下面这样:

主线程中的x:1
主线程中的x:2
t1的x:1
主线程中的x:3
t1的x:2
t2的x:1
主线程中的x:4
t1的x:3
主线程中的x:5
t2的x:2
t1的x:4
t2的x:3
t1的x:5
t2的x:4
t2的x:5

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
PHP开发工程师
手记
粉丝
10
获赞与收藏
54

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消