0

0

c# ManualResetEvent 和 AutoResetEvent 的区别和用法

月夜之吻

月夜之吻

发布时间:2026-01-12 12:00:02

|

458人浏览过

|

来源于php中文网

原创

AutoResetEvent与ManualResetEvent的核心区别在于重置责任:前者WaitOne()唤醒一个线程后自动Reset(),后者唤醒所有线程后保持信号状态直至手动Reset();初始化推荐false以避免竞态,使用后须Dispose()防止句柄泄漏。

c# manualresetevent 和 autoresetevent 的区别和用法

网钛淘拍CMS(TaoPaiCMS) V1.60
网钛淘拍CMS(TaoPaiCMS) V1.60

2013年07月06日 V1.60 升级包更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有文件覆盖进去。1.[新增]后台引导页加入非IE浏览器提示,后台部分功能在非IE浏览器下可能没法使用2.[改进]淘客商品管理 首页 列表页 内容页 的下拉项加入颜色来区别不同项3.[改进]后台新增/修改淘客商品,增加淘宝字样的图标和天猫字样图标改成天猫logo图标4.[改进]为统一名称,“分类”改

下载

WaitOne() 行为差异是核心区别

不是“能不能用”,而是“用完要不要管”: AutoResetEvent.WaitOne() 每次唤醒**一个**等待线程后,**自动调用 Reset()**,事件立刻回到无信号(false)状态; ManualResetEvent.WaitOne() 唤醒**所有**当前等待线程后,**保持有信号(true)状态不变**,直到你手动调用 Reset()

  • 没调 Reset()ManualResetEvent,后续所有 WaitOne() 都直接通过——相当于“闸门一直开着”
  • 没调 Set()AutoResetEvent,哪怕只差 1 毫秒,WaitOne() 就会永久阻塞(除非超时)
  • 两个类的 WaitOne(1000) 都支持超时,超时返回 false,不抛异常

构造函数参数 initialState 决定“第一次是否拦人”

new AutoResetEvent(false)new ManualResetEvent(false) 是最常用写法: 首次 WaitOne() 必然阻塞,必须等别人 Set() 才能继续。 而 new AutoResetEvent(true) 相当于“开门即放行一次”,第一个 WaitOne() 立刻返回,之后立即变回 falsenew ManualResetEvent(true) 则是“门一开始就开着”,所有 WaitOne() 都直接过,直到你 Reset()

  • 别靠猜——用 false 初始化最安全,逻辑清晰
  • true 初始化容易引发竞态:比如主线程刚 new 完,子线程就 WaitOne() 了,结果啥都没等就往下跑了

典型使用场景不能混用

选错类型会导致线程“该醒不醒”或“不该醒全醒了”:

  • 生产者-消费者单次通知(如:一个任务完成,唤醒一个处理线程)→ 用 AutoResetEvent (例:日志写入线程完成 flush 后,只唤醒一个归档线程)
  • 初始化完成广播(如:配置加载完毕,让所有工作线程同时开始)→ 用 ManualResetEvent (例:主线程加载完配置后 Set(),5 个后台服务线程在 WaitOne() 处一起启动)
  • 资源池限流(如:最多允许 3 个线程并发访问)→ 不该用这两个,该用 SemaphoreSlim

常见错误和坑点

实际调试中最容易栽在这几处:

  • AutoResetEvent.Set() 被多次快速调用,但只有一个线程被唤醒——因为第二次 Set() 发生在第一次唤醒+自动 Reset() 之前,信号被“覆盖”了
  • 忘记给 ManualResetEvent 调用 Reset(),导致后续测试中 WaitOne() 总是秒过,行为不可复现
  • using 块里创建事件对象,但没 Dispose() —— 这俩都实现了 IDisposable,长期运行的服务必须释放句柄,否则泄漏内核对象
  • WaitOne() 放在 UI 线程(如 WinForms/WPF)且不加超时,一旦漏掉 Set(),整个界面就卡死
var auto = new AutoResetEvent(false);
var manual = new ManualResetEvent(false);

// 错误示范:没 Dispose
Task.Run(() => {
    auto.WaitOne(); // 等信号
    Console.WriteLine("auto done");
});

// 正确做法(尤其服务端)
try
{
    if (auto.WaitOne(5000)) // 加超时
        Console.WriteLine("auto done");
    else
        Console.WriteLine("timeout");
}
finally
{
    auto.Dispose(); // 必须释放
}
ManualResetEvent 和 AutoResetEvent 的本质区别不在“谁更高级”,而在“谁负责重置”。用错不是报错,而是逻辑静默失效——线程该等不等、该停不停,这种 bug 往往要压测几天才暴露。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

34

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

14

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

33

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

18

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号