C#多线程---Event类实现线程同步
一、简介
我们使用类(.net Framework中的类,如 AutoResetEvent, Semaphore类等)的方法来实现线程同步的时候,其实内部是调用操作系统的内核对象来实现的线程同步。
System.Threading命名空间中提供了一个WaitHandle 的抽象基类,此类就是包装了一个Windows内核对象的句柄(句柄可以理解为标示了对象实例的一个数字),在.net Framework中提供了从WaitHandle类中派生的类。继承关系如下所示:
WaitHandle
EventWaitHandle
AutoResetEvent
ManualResetEvent
Semaphore
Mutex
当我们在使用 AutoResetEvent,ManualResetEvent,Semaphore,Mutex这些类的时候,用构造函数来实例化这些类的对象时,其内部都调用了Win32 CreateEvent或CreateEvent函数,或CreateSemaphore或者CreateMutex函数,这些函数调用返回的句柄值都保存在WaitHandle基类定义的SafeWaitHandle字段中。
二、AutoResetEvent (自动重置事件)
AutoResetEvent 在获得信号后,会自动将事件设置为无信号状态。
例1:事件初始化为无信号状态,主线程等待一段时间将事件设置为有信号状态
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
7
8 namespace ThreadEvent
9 {
10 class Program
11 {
12 public static AutoResetEvent autoEvent = new AutoResetEvent(false);
13 static void Main(string[] args)
14 {
15 Task task = new Task(ThreadFunc);
16 task.Start();
17 Console.WriteLine($"{DateTime.Now} Printed in main");
18 Thread.Sleep(5000);
19 Console.WriteLine($"{DateTime.Now} Set signal in main");
20 autoEvent.Set();
21 Console.Read();
22 }
23 private static void ThreadFunc()
24 {
25 PrintThreadInfo($"Printed in thread func");
26 }
27 private static void PrintThreadInfo(string info)
28 {
29 if (autoEvent.WaitOne())
30 {
31 //autoEvent.WaitOne();
32 Console.WriteLine($"{DateTime.Now} {info}");
33 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}");
34 }
35
36 }
37 }
38 }
运行结果如下:

例2:事件初始化为无信号状态,主线程等待一段时间将事件设置为有信号状态,子线程连续两次Wait,观察第二次Wait的结果
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
7
8 namespace ThreadEvent
9 {
10 class Program
11 {
12 public static AutoResetEvent autoEvent = new AutoResetEvent(false);
13 static void Main(string[] args)
14 {
15 Task task = new Task(ThreadFunc);
16 task.Start();
17 Console.WriteLine($"{DateTime.Now} Printed in main");
18 Thread.Sleep(5000);
19 Console.WriteLine($"{DateTime.Now} Set signal in main");
20 autoEvent.Set();
21 Console.Read();
22 }
23 private static void ThreadFunc()
24 {
25 PrintThreadInfo($"Printed in thread func");
26 }
27 private static void PrintThreadInfo(string info)
28 {
29 if (autoEvent.WaitOne())
30 {
31 if (autoEvent.WaitOne(4000))
32 {
33 Console.WriteLine($"{DateTime.Now} {info}");
34 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}");
35 }
36 else
37 {
38 Console.ForegroundColor = ConsoleColor.Red;
39 Console.WriteLine($"{DateTime.Now} WaitOne timeout!");
40 Console.ResetColor();
41 }
42 }
43
44 }
45 }
46 }
运行结果如下:

三、ManualResetEvent(手动重置事件)
ManualResetEvent在获得信号后,会一直保持有信号状态,除非我们手动调用Reset来将事件设置为无信号状态。
例1:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
7
8 namespace ThreadEvent
9 {
10 class Program
11 {
12 public static ManualResetEvent autoEvent = new ManualResetEvent(false);
13 static void Main(string[] args)
14 {
15 Task task = new Task(ThreadFunc);
16 task.Start();
17 Console.WriteLine($"{DateTime.Now} Printed in main");
18 Thread.Sleep(5000);
19 Console.WriteLine($"{DateTime.Now} Set signal in main");
20 autoEvent.Set();
21 Console.Read();
22 }
23 private static void ThreadFunc()
24 {
25 PrintThreadInfo($"Printed in thread func");
26 }
27 private static void PrintThreadInfo(string info)
28 {
29 if (autoEvent.WaitOne())
30 {
31 //autoEvent.Reset();
32 if (autoEvent.WaitOne(4000))
33 {
34 Console.WriteLine($"{DateTime.Now} {info}");
35 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}");
36 }
37 else
38 {
39 Console.ForegroundColor = ConsoleColor.Red;
40 Console.WriteLine($"{DateTime.Now} WaitOne timeout!");
41 Console.ResetColor();
42 }
43 }
44
45 }
46 }
47 }
运行结果如下:

C#多线程---Event类实现线程同步的更多相关文章
- C#多线程---Mutex类实现线程同步
一.例子 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 ...
- C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)
本篇继续介绍WaitHandler类及其子类 Mutex,ManualResetEvent,AutoResetEvent的用法..NET中线程同步的方式多的让人看了眼花缭乱,究竟该怎么去理解呢?其实, ...
- Python多线程(2)——线程同步机制
本文介绍Python中的线程同步对象,主要涉及 thread 和 threading 模块. threading 模块提供的线程同步原语包括:Lock.RLock.Condition.Event.Se ...
- java多线程(2) 线程同步
我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步. 例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- Java多线程之简单的线程同步实例
数据类: package Thread.MyCommon; public class Data { public int num = 0; public synchronized int getEve ...
- iOS多线程各种安全锁介绍 - 线程同步
一.atomic介绍 github对应Demo:https://github.com/Master-fd/LockDemo 在iOS中,@property 新增属性时,可以增加atomic选项,ato ...
- win32多线程 (二)线程同步之临界区 (critical sections)
所谓critical sections 意指一小块“用来处理一份被共享之资源”的程序代码.你可能必须在程序的许多地方处理这一块可共享的资源.所有这些程序代码可以被同一个critical sectio ...
- C#线程学习笔记五:线程同步--事件构造
本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Event_Constructor.html,记录一下学习过程以备后续查用. 前面讲的线 ...
随机推荐
- 使用python对工作簿每个sheet表进行数据可视化展示(本案例是从第2个sheet开始循环读取也就是索引为1的表)
# 导入相关模块from pyecharts.charts import Barfrom pyecharts import options as optsfrom pyecharts.charts i ...
- [刘阳Java]_酷炫视频播放器制作_JS篇
此文章是接着上次写的<酷炫视频播放器制作_界面篇>将其完善,我们主要给大家介绍一下如何利用JS脚本来控制视频的播放.为了让大家能够保持对要完成的功能有直接的了解,我们还是将效果图附到文章里 ...
- 自动执行文件夹中的py文件
写一个函数,接收一个地址,执行其中的py文件,包括子文件.path.endswith('.py') 判断以'.py'结尾,是什么类型的文件.os.system('python %s'%path) 模拟 ...
- Allure测试框架 python
关于Allure Allure是一个report框架,可以基于一些测试框架生成测试报告,比较常用的一般是Junit/Testng框架: Allure 生成的报告样式简洁美观,同时又支持中文: Allu ...
- Java字节码增强技术
简单介绍下几种java字节码增强技术. ASM ASM是一个Java字节码操控框架,它能被用来动态生成类或者增强既有类的功能.ASM可以直接产生class文件,也可以在类被加载入Java虚拟机之前动态 ...
- proteus8.1 pro 中文版安装破解教程
Proteus8 Pro是非常有名的EDA工具(仿真软件),从原理图布图.代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计.是唯一将电路仿真软件.PCB设计软 ...
- sessionfilter中的拦截项判断
- salesforce Integration 概览(一) 杂篇
本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 我们在做sales ...
- 记一次 GitLab 的迁移过程
目录 1. 迁移背景 2. GitLab 整体架构介绍 3. GitLab 安装 配置选择 安装方式选择 安装的网络区域 安装 GitLab GitLab 常用命令 配置管理员账号密码 4. 配置 G ...
- [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构
[源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 目录 [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 0x00 摘要 0x01使用 1.1 配置 ...