.NET 多线程开发总结(三)——线程间的信号传递(线程交互)

本文详细介绍了.NET中线程同步的基础知识,重点讲解了WaitHandle及其派生类EventWaitHandle的使用,包括构造函数、常见方法及上下文同步的原理与应用。

本节内容相对来说比较基础,但也是为了后面的文章做铺垫,因此个人觉得有必要单独拿出来写一写。

一、线程间的信号传递

我们知道,线程之间的关系是异步的,谁也不干预谁。但在实际执行过程中,有时需要线程可以做到同步,即一方等待另一方的通知,再继续执行下一步。
这时候,就需要有一个东西,既能够阻止等待方的执行,又能够让另一方执行到某一处时告知前者,“我已执行完毕,你可以继续了”。于是,微软便提供了这样一个对象,叫做WaitHandle。它是互斥量和同步信号量的基元,也是一个抽象类,因此我们使用它时要根据情况使用它派生的各个子类。
下图展示了WaitHandle是如何进行工作的:

在这里插入图片描述
二、线程同步事件(EventWaitHandle)

EventWaitHandle是最基础的线程同步事件类,AutoResetEventManualResetEvent都是派生自此类,不过仅仅外包了一层构造函数,并没有增加其他的方法和属性。不仅没有增加,反而隐藏了给事件命名的构造方法。要知道,基于WaitHandle的对象都是可以在操作系统中访问到的,也就是可以跨进程访问,如果不能给对象命名,那么这一功能将会丧失。(可能微软也不希望这么用,因为多个线程同时等待一个信号时,无法决定谁先接收到信号,如果用了AutoReset模式,这将会很糟糕【只有一个线程能收到,而且不确定谁会收到= =】)

所以接下来我打算只介绍EventWaitHandle最常见的使用:

1、构造
关于EventWaitHandle的构造函数,有多个重载,比较常用的构造函数如下

public EventWaitHandle(bool initialState, EventResetMode mode);

第一个参数表示是否在初始时将状态设置为终止状态,说得直白点就是设置最开始是否为收到信号的状态,如果是,则接下来的第一个等待将不会阻止线程;
第二个参数表示设置事件重置的方式,也就是当收到信号时,是否自动把已接收状态变为未接收状态。这里如果设为True,就相当于AutoResetEvent;如果是False,就相当于ManualResetEvent。

2、常用方法
Set():将线程同步事件标记为有信号,此时处于阻塞等待状态的线程将会停止等待。如果模式为AutoReset,那么还会自动触发Reset()方法。
Reset():将线程同步事件标记为无信号。
WaitOne():阻止当前线程,直到收到信号。该方法的另外一些重载,可以允许设置等待超时时间,并决定是否在等待前退出当前上下文(关于上下文,会在文字后面补充说明)
WaitAny():等待一个同步事件数组中任意一个元素收到信号
WaitAll():等待一个同步事件数组中所有元素都收到信号
SignalAndWait():该方法会传入两个同步事件对象,作用是给前者发出信号,再等待后者收到信号

这里要特别说明最后一个方法,因为它比较特殊。前面几种等待方法,都是一个线程等待另一个或几个线程的信号,再继续做自己的事。而最后一个方法,则运用在两个线程需要互相等待的情况。
下面举个栗子:
在这里插入图片描述

如图所示,A、B线程并行执行过程1,但B要执行过程2需等待A执行完过程1发出信号,A要执行过程2需等待B执行完过程2发出信号。如此实现了一个 A.过程1—>B.过程2—>A.过程2 的一个同步。
下面上代码:

static void Main(string[] args)
{
   
   
    EventWaitHandle eventWaitA = new EventWaitHandle(false, EventResetMode.AutoReset);
    EventWaitHandle eventWaitB = 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值