一、简介

我们使用类(.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类实现线程同步的更多相关文章

  1. C#多线程---Mutex类实现线程同步

    一.例子 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 ...

  2. C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)

    本篇继续介绍WaitHandler类及其子类 Mutex,ManualResetEvent,AutoResetEvent的用法..NET中线程同步的方式多的让人看了眼花缭乱,究竟该怎么去理解呢?其实, ...

  3. Python多线程(2)——线程同步机制

    本文介绍Python中的线程同步对象,主要涉及 thread 和 threading 模块. threading 模块提供的线程同步原语包括:Lock.RLock.Condition.Event.Se ...

  4. java多线程(2) 线程同步

    我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步.   例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...

  5. Java多线程系列三——实现线程同步的方法

    两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...

  6. Java多线程之简单的线程同步实例

    数据类: package Thread.MyCommon; public class Data { public int num = 0; public synchronized int getEve ...

  7. iOS多线程各种安全锁介绍 - 线程同步

    一.atomic介绍 github对应Demo:https://github.com/Master-fd/LockDemo 在iOS中,@property 新增属性时,可以增加atomic选项,ato ...

  8. win32多线程 (二)线程同步之临界区 (critical sections)

    所谓critical sections 意指一小块“用来处理一份被共享之资源”的程序代码.你可能必须在程序的许多地方处理这一块可共享的资源.所有这些程序代码可以被同一个critical  sectio ...

  9. C#线程学习笔记五:线程同步--事件构造

    本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Event_Constructor.html,记录一下学习过程以备后续查用. 前面讲的线 ...

随机推荐

  1. C语言:2.2.1-4

    #include <stdio.h> #define PI 3.1415926 //宏定义末尾没有分别.如果有则成为字符串的一部分 int main() { printf("显示 ...

  2. POJ 树的直径和重心

    树的直径:(无根)树上最长两点间的最长路径,两次dfs即可,第一次dfs任选一点u,找到距离它最远的点s,再从点s进行一次dfs,找到距离s最远的点t,则s-t之间的路径就是树的直径.证明: < ...

  3. python -- 结构数据类型(列表、元组、集合、字典)

    一.列表 列表表示一组有序的元素,这些元素可以是数字.字符串,也可以是另一个列表. # ----------------------------------------# 列表(list):一组有序的 ...

  4. Selnium + POM + Pytest:学习记录

    简介 selenium POM Pytest 结合,通过Pytest fixture 来传递Driver 保证一个测试用例[1] :driver[1] 学习记录 插件包 selenium: 操作浏览器 ...

  5. Selenium3自动化测试【20】CSS定位元素

    CSS 指层叠样式表 (CascadingStyleSheets),CSS一种用来表现HTML或XML等文件样式的计算机语言,其能够灵活的为页面提供丰富样式的风格. CSS使用选择器为页面元素绑定属性 ...

  6. 在 Golang 中实现一个简单的Http中间件

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的 ...

  7. C++第四十六篇 -- C++将int转换成宽字符串

    int rate = 60; int score = 80 TCHAR Temp[64] = TEXT(""); _stprintf_s(Temp, TEXT("pass ...

  8. 添加xxx到右键菜单

    1. 添加notepad++到右键菜单[1] 添加到 右键菜单 将以下内容保存为 OpenWithNotepad++.reg 文件,双击运行即可(其中可执行文件路径和菜单项名称请自行替换): 注: 下 ...

  9. SSH远程端口转发实战详解

    问题 前段时间在外地没有在实验室,随身携带了一个笔记本电脑.但是笔记本性能不够,想用SSH远程连接实验室的电脑.问如何连接?现有以下设备 设备 IP 备注 系统 实验室电脑C1 192.168.0.2 ...

  10. Hadoop 3.1.1 - 概述 - 总览

    Apache Hadoop 3.1.1 和之前发布的 3.0.X 版本线相比,Apache Hadoop 3.1.1 吸收了许多重要的改进. 总览 建议用户阅读完整的版本说明.本文提供了对主要变动的总 ...