多线程中的ManualResetEvent

简介: 先来看一下简单的多线程控制台程序:using System;using System.Threading;namespace ManualResetEventStudy{    class ThreadClass    {        static void t1()        {    ...

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

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

 

 

 

目录
相关文章
|
8月前
|
C#
C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信
在多线程编程中,AutoResetEvent 和 ManualResetEvent 是两个常用的同步原语。它们用于线程间的通信和协调,以确保线程按照特定的顺序执行。本篇博客将介绍这两种同步原语的概念、用法和区别。
128 0
C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信
C# 使用ManualResetEvent 进行线程同步
上一篇我们介绍了AutoResetEvent,这一篇我们来看下ManualResetEvent ,顾名思义ManualResetEvent  为手动重置事件。 AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。
846 0
C#多线程之二:ManualResetEvent和AutoResetEvent
转自博客:http://www.cnblogs.com/charley_yang/archive/2010/10/31/1865663.html 初次体验 ManualResetEvent和AutoResetEvent主要负责多线程编程中的线程同步;以下一段是引述网上和MSDN的解析: 在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。
1081 0
|
Windows
重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent
原文:重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent [源码下载] 重新想象 Windows 8 Store Apps (...
710 0
|
12天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
37 1
|
3月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
62 1
|
3月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
41 3
|
3月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
28 2
|
3月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
45 2