当前位置: 首页 > news >正文

C# AutoResetEvent和ManualResetEvent

AutoResetEventManualResetEvent 是 .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

http://www.dtcms.com/a/581956.html

相关文章:

  • AI驱动半导体良率提升:基于机器学习的晶圆缺陷分类系统搭建
  • 系统架构师·案例分析相关知识点
  • 建站公司前景网站运营有前途吗
  • Leetcode 48
  • 因需写了个内网运维专用的IP地址管理工具,有点不同
  • 沈阳seo整站优化网页设计大师
  • 瓯北网站制作公司怎么用思维导图做网站结构图
  • 【代码随想录算法训练营——Day61】图论——97.小明逛公园、127.骑士的攻击
  • [Dify 实战] 使用 System Prompt 实现企业级策略管控
  • JVM架构与执行流程详解
  • 02 Prompt组件及使用技巧
  • 做网站能用微软企业公示信息年报
  • 本地赣州网站建设网站建设数据库选择
  • 多维竞争时代:手游ASO优化核心策略与安卓商店差异化
  • Linux命令-e2label命令(设置第二扩展文件系统的卷标)
  • 企业AI开发什么工具好?从“可用”到“好用”的全生命周期管理指南
  • (Linux)ELF格式与库的链接原理
  • 如何做网站的营销网站技术防护建设
  • C++新特性 chr类型编码
  • 指纹浏览器模拟功能的实践体验分享
  • C++ 设计模式《订单的撤销和重做》
  • 国网法治建设网站阿里巴巴推广平台
  • 【AI学习-comfyUI学习-SDXL 风格化提示词节点包(Style Prompt Node Pack) 工作流-各个部分学习-第四节】
  • 怎样建设有价值的网站天津建设工程信息网中标公告
  • 提升大语言模型性能的关键技术清单(from 网络)
  • 【NLP】Penn Treebank 与 Parsing:让计算机看懂句子结构
  • Go 1.25 发布:性能、工具与生态的全面进化
  • 北京市保障性住房建设投资中心网站淮南吧
  • Duilib_CEF桌面软件实战之Duilib编译与第一个界面程序
  • MFC动态加载图片