首页 > 编程语言 >C#中使用AutoResetEvent或者ManualResetEvent做线程管理

C#中使用AutoResetEvent或者ManualResetEvent做线程管理

时间:2024-06-13 13:44:43浏览次数:13  
标签:C# ManualResetEvent AutoResetEvent static 线程 new my

1. Task/thread/sync/async..await/WhenAll
相关基础知识参见此处链接

2. 什么是AutoResetEvent和ManualResetEvent事件

  • 他们都是C#中System.Threading下面的类。用于在多个线程之间进行事件通知和管理。
  • 他们的管理方法主要是三个:
    • Reset():关闭
    • WaitOne():阻挡
    • Set():启动
  • AutoResetEvent和ManualResetEvent的区别
    • 自动方法遵循set -> WaitOne -> Reset的流程自动执行,但是自动方法的一个set只能控制一个线程
    • 手动方法也是遵循set -> WaitOne -> Reset的流程,但是手动方法可以灵活的进行手动控制,一个手动的set可以控制多个同步线程。

3. 理解

  • 不管是auto还是manual,都要经历的步骤如下(其他地方看到一个很形象的举例):
车辆过高速收费站时:
自动:车闸默认关闭(new AutoResetEvent(false)) -> 车辆到达收费站被阻(waitone()) -> 交费,然后开闸(set()) -> 关闭车闸(reset())

手动:车闸打开后(set()),并不会自动关闭,所以如果不去手动关闭(reset()),后面的车会一辆一辆的通过。

自动可以自动关闭车闸(reset()),让一次只能过一个车,特点就是自动情况下,同步存在两个同步线程,最终只能执行第一个线程。
手动需要手动关闭车闸(reset()),特点就是手动情况下,如果不手动reset(),所有线程都会被依次执行完毕。
WaitOne()是否生效取决于有没有Reset()。如果一开始就是Reset()的,那么WaitOne不会阻挡任何线程执行。

4. AutoResetEvent和ManualResetEvent的初始化状态

  • new Auto/ManualResetEvent(false):默认阻挡线程。
  • new Auto/ManualResetEvent(true):默认通过线程。
  • new Auto/ManualResetEvent(true)中,WaitOne没有任何意义,它阻挡不了线程

5. auto/manual测试代码

  • autoresetevent中的验证代码:
internal class Program
{
    static EventWaitHandle my_task1 = new AutoResetEvent(true);//默认自动执行
    static AutoResetEvent my_task2 = new AutoResetEvent(false);//默认自动阻挡
    //static ManualResetEvent my_task3 = new ManualResetEvent(false);//默认手动阻挡
    private static void Main(string[] args)
    {
        //thread
        new Thread(func1).Start();
 
        new Thread(func3).Start();

        my_task2.Set();//开启,因为func3的调用在func2的上面,所以set先管理到func3。func3能执行,func2不能执行,这表明autoresetevent是典型的队列操作形式

        new Thread(func2).Start();

        Console.ReadKey();
    }
    static void func1()
    {
        my_task1.WaitOne();
        Console.WriteLine("此时的waitOne不能阻挡线程执行");
    }
    static void func2()
    {
        my_task2.WaitOne();
        Console.WriteLine("此时的waitOne会阻挡线程执行");
    }
    static void func3()
    {
        my_task2.WaitOne();
        Console.WriteLine("此时的waitOne会阻挡线程执行,开启set后通过");
    }
}

输出结果:

  • manualresetevent中的验证代码
internal class Program
{
    //static EventWaitHandle my_task1 = new AutoResetEvent(true);//默认自动执行
    //static AutoResetEvent my_task2 = new AutoResetEvent(false);//默认自动阻挡
    static ManualResetEvent my_task3 = new ManualResetEvent(false);//默认手动阻挡
    private static void Main(string[] args)
    {
        //thread
        new Thread(func1).Start();
 
        new Thread(func2).Start();

        new Thread(func3).Start();

        my_task3.Set();//手动set一次,执行多个线程

        Timer my_time = new Timer(CloseDown,null,0,2000);//2秒计时器

        Console.ReadKey();
    }
    static void func1()
    {
        my_task3.WaitOne();
        Console.WriteLine("手动第一次执行");
    }
    static void func2()
    {
        my_task3.WaitOne();
        Console.WriteLine("手动第二次执行");
    }
    static void func3()
    {
        my_task3.WaitOne();
        Console.WriteLine("手动第三次执行");
    }
    static void func4()
    {
        Thread.Sleep(3000);//等待3秒,大于reset时间,故不会执行
        my_task3.WaitOne();
        Console.WriteLine("不会执行第四次");
    }

    /// <summary>
    /// 2秒后关闭线程
    /// </summary>
    /// <param name="o"></param>
    static void CloseDown(object o)
    { 
    my_task3.Reset();
    }

}

输出结果:

6. 总结

  • auto一次只能执行一个线程
  • manual开启后可以同步执行超多线程
  • AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();
  • 多个线程的暂停,继续,可以选择Manual。

标签:C#,ManualResetEvent,AutoResetEvent,static,线程,new,my
From: https://www.cnblogs.com/xiacuncun/p/18245624

相关文章

  • anaconda里虚拟环境安装jupyter notebook
    安装jupyternotebook打开anacondaprompt,进入虚拟环境condaactivatePytorch_learning下载安装jupyternotebookcondainstalljupyternotebook或用pip安装pipinstalljupyter运行jupyternotebook进入环境之后,输入命令jupyternotebook运行完成后会自动打开浏......
  • 从零开始写 Docker(十八)---容器网络实现(下):为容器插上”网线“
    本文为从零开始写Docker系列第十八篇,利用linux下的Veth、Bridge、iptables等等相关技术,构建容器网络模型,为容器插上”网线“。完整代码见:https://github.com/lixd/mydocker欢迎Star推荐阅读以下文章对docker基本实现有一个大致认识:核心原理:深入理解Docker核心......
  • The Enchantment of the Dragon Boat Festival
    TheEnchantmentoftheDragonBoatFestivalAstheearlyJuneiscoming,theringoftheDragonBoatFestivalhadunconsciouslyknocked.IwastransportedbacktotheenchantingatmosphereoftheDragonBoatFestival.Thisfestival,deeplyrootedinChin......
  • DCL、约束、索引语法
    数据库相关语法DCL:开子账号:登录子账号:添加权限:删除权限:删除子账号:设置编码格式:数据类型:数值类型:整数类型:浮点类型:字符串类型:日期时间类型:约束:主键约束:添加:删除:唯一约束:非空约束:外键约束:场景:索引:主键索引:添加:删除:唯一索引:普通索引:全文索引:面试题:DCL:......
  • Q27 LeetCode350 两个数组交集取小
    使用hashmap记录数字个数,如果nums1中重复数字多,遍历2时则不需要取少如果2中重复数字多,则每次取到就-1,直至map内无值  1classSolution{2publicint[]intersect(int[]nums1,int[]nums2){3HashMap<Integer,Integer>map=newHashMap<>();4......
  • ABC357
    Alink循环加每一个数,加到哪个数不能加了输出前一个数,注意如果加到最后还能加,记得输出\(n\)。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,m;inth[105],sum;signedmain(){ cin>>n>>m; for(inti=1;i<=n;++i) cin>>h[i]; for......
  • boost-Asio 基础学习2 --socket 服务端和客户端简单通讯
    已经写了两期文章了!这是第三期现在也到使用asio库实现一些基础的小功能了......
  • BGP路由优选实验(包含as策略,Community属性等)
    实验背景实验目的1.使用AS_PATH属性,确保R4通过R3到达192.168.11.0/242.使用LOCAL_PREF属性,确保R1通过R2到达192.168.1.0/243.使用MED属性,确认R4通过R3到达192.168.12.0/244.使用LOCAL_PREF属性,确保R1通过R3到达192.168.2.0/245.使用AS策略,AS500不接受任何始发于AS1......
  • 专用向量数据库:Watch your back!
    PostgreSQL生态再添利器:Timescale最新推出了两款创新的开源扩展——pgvectorscale和pgai,喊话专用向量数据库:Watchyourback!性能和成本效率创新高pgvectorscale扩展基于StreamingDiskANN索引和Timescale的统计二进制量化技术,在性能上取得了显著进步。基准测试显示,使用pgvecto......
  • 极限网关助力好未来 Elasticsearch 容器化升级
    极限网关在好未来的最佳实践案例,轻松扛住日增百TB数据的流量,助力ES从物理机到云原生架构的改造,实现了流控、请求分析、安全管理、无缝迁移等场景。一次完美的客户体验~背景物理机架构时代2022年,好未来整个日志Elasticsearch拥有数十套服务集群,几百台物理机。这么多台......