C# AutoResetEvent和ManualResetEvent的实现示例

 更新时间:2025年11月27日 10:40:17   作者:她说彩礼65万  
本文主要介绍了C# AutoResetEvent和ManualResetEvent的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

AutoResetEvent 和 ManualResetEvent 是 .NET 中用于线程同步的两个重要类,都继承自 EventWaitHandle。它们的核心区别在于 “信号触发后是否自动重置状态”。

✅ 一句话总结区别:

  • AutoResetEvent:
    信号触发(Set)后,只允许一个等待线程通过,然后自动重置为非信号状态(false)。

  • ManualResetEvent:
    信号触发(Set)后,所有等待线程都可以通过,并且保持信号状态(true),直到你手动调用 Reset() 才关闭。

🔍 详细对比

特性AutoResetEventManualResetEvent
初始状态可指定(默认 false)可指定(默认 false)
调用 Set() 后允许一个等待线程继续执行,然后自动变为 false所有等待线程继续执行,并保持 true
如何关闭信号自动关闭(无需干预)必须显式调用 Reset()
类比旋转门(一次只过一人)闸门(打开后所有人都能过,直到手动关上)
典型用途线程间一对一通知、生产者-消费者单次唤醒多线程同时启动/停止、初始化完成广播

💡 代码示例说明

示例 1:AutoResetEvent—— 一次只唤醒一个线程

var are = new AutoResetEvent(false);

// 启动3个等待线程
for (int i = 0; i < 3; i++)
{
    int id = i;
    Task.Run(() =>
    {
        Console.WriteLine($"线程 {id} 等待中...");
        are.WaitOne(); // 阻塞直到收到信号
        Console.WriteLine($"线程 {id} 被唤醒!");
    });
}

Thread.Sleep(1000);
Console.WriteLine("主线程发出信号...");

are.Set(); // ⚠️ 只会唤醒 ONE 线程!
Thread.Sleep(100); 
are.Set(); // 再唤醒一个
Thread.Sleep(100);
are.Set(); // 再唤醒最后一个

输出(顺序可能不同)

线程 0 等待中...
线程 1 等待中...
线程 2 等待中...
主线程发出信号...
线程 1 被唤醒!
线程 0 被唤醒!
线程 2 被唤醒!

✅ 每次 Set() 只放行一个线程,之后自动关闭。

示例 2:ManualResetEvent—— 一次性唤醒所有线程

var mre = new ManualResetEvent(false);

for (int i = 0; i < 3; i++)
{
    int id = i;
    Task.Run(() =>
    {
        Console.WriteLine($"线程 {id} 等待中...");
        mre.WaitOne();
        Console.WriteLine($"线程 {id} 被唤醒!");
    });
}

Thread.Sleep(1000);
Console.WriteLine("主线程发出信号...");
mre.Set(); // 🔓 所有等待线程立即通过!

// 不需要多次 Set,也不自动关闭

输出

线程 0 等待中...
线程 1 等待中...
线程 2 等待中...
主线程发出信号...
线程 2 被唤醒!
线程 0 被唤醒!
线程 1 被唤醒!

✅ 一次 Set(),全部放行!
❗ 如果之后再有线程调用 WaitOne(),也会立即通过(因为信号仍为 true),除非你调用 mre.Reset()。

🛠 常见使用场景

✅AutoResetEvent适用场景:

  • 生产者-消费者模型:每次生产一个数据,唤醒一个消费者。
  • 线程池任务分发:一个任务就绪,通知一个工作线程处理。
  • 精确控制单次唤醒

✅ManualResetEvent适用场景:

  • 程序初始化完成广播:等所有资源加载完,通知所有线程开始工作。
  • 并行测试启动:让多个线程同时开始执行(避免先后差异)。
  • 全局暂停/恢复控制:如游戏暂停系统。
// 初始化完成示例
var initComplete = new ManualResetEvent(false);

Task.Run(() => {
    LoadConfig();
    LoadDatabase();
    initComplete.Set(); // 所有准备工作完成
});

// 多个工作线程等待初始化完成
Task.Run(() => {
    initComplete.WaitOne(); // 等待初始化
    DoWork();
});

⚠️ 注意事项

  1. 性能:两者都是内核对象(Kernel Object),涉及用户态 ↔ 内核态切换,频繁使用有开销。高频场景可考虑 SpinWaitMonitor
  2. 替代方案(.NET Core / .NET 5+)
    • 使用 TaskCompletionSource<T> 实现异步通知(更现代)
    • 使用 CountdownEventBarrier 等高级同步原语
  3. 不要混淆 Reset() 行为
    • AutoResetEventReset() 是多余的(它自己会重置)
    • ManualResetEvent 必须手动 Reset() 才能再次阻塞线程

✅ 总结记忆口诀:

  • Auto自动关门(过一人,门自动关)
  • Manual手动关门(门开了,所有人能过,得你手动关)

选择哪个?
👉 需要逐个唤醒?用 AutoResetEvent
👉 需要集体唤醒?用 ManualResetEvent

到此这篇关于C# AutoResetEvent和ManualResetEvent的实现示例的文章就介绍到这了,更多相关C# AutoResetEvent和ManualResetEvent内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#实现批量下载图片到本地示例代码

    C#实现批量下载图片到本地示例代码

    这篇文章主要给大家介绍了关于C#如何实现批量下载图片到本地的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • C# .net core HttpClientFactory用法及说明

    C# .net core HttpClientFactory用法及说明

    这篇文章主要介绍了C# .net core HttpClientFactory用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • WinForm中快捷键与组合按键的设置方法

    WinForm中快捷键与组合按键的设置方法

    WinForm中快捷键与组合按键的设置,第一种方法。。代码复杂,操作简单的快捷键,另外一种简单快捷键的方法,大家可以参考下
    2013-02-02
  • C#实现接收QQ邮件的示例代码

    C#实现接收QQ邮件的示例代码

    这篇文章主要为大家详细介绍了C#如何使用pop协议来实现一下接收QQ邮件的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-08-08
  • C#常用数据结构之数组Array

    C#常用数据结构之数组Array

    这篇文章介绍了C#常用数据结构之数组Array,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#转换日期类型实例

    C#转换日期类型实例

    这篇文章主要介绍了C#转换日期类型的方法,以实例形式分析了将日期格式转换为Unix时间戳与时区结合的形式,是比较实用的技巧,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • C#条码生成类分享

    C#条码生成类分享

    这篇文章主要分享了C#条码生成类的实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 基于WPF实现绘制地铁路线图

    基于WPF实现绘制地铁路线图

    经常坐地铁,却不知道地铁多少条线路?哪个站下车?本文就来带大家利用WPF绘制深圳地铁路线图,从而带大家掌握WPF在图形绘制方面的一些知识,希望对大家有所帮助
    2023-06-06
  • VS2010中lib与dll文件的生成与使用方法

    VS2010中lib与dll文件的生成与使用方法

    这篇文章主要介绍了VS2010中lib与dll文件的生成与使用方法,需要的朋友可以参考下
    2018-01-01
  • c# WPF中的TreeView使用详解

    c# WPF中的TreeView使用详解

    这篇文章主要介绍了c# WPF中的TreeView使用详解,帮助大家更好的理解和学习使用c#技术,感兴趣的朋友可以了解下
    2021-03-03

最新评论