上海微网站设计,网站开发人员应该用什么浏览器,wordpress实现微信登录界面,免费搭建个人网站的3种实用方法总目录 前言
ManualResetEvent 是 C# 中用于线程同步的核心类之一#xff0c;位于 System.Threading 命名空间下。它的核心功能是通过信号机制控制线程的执行顺序#xff0c;允许一个或多个线程等待某个信号后再继续运行。与 AutoResetEvent 不同#xff0c;ManualResetEve…总目录 前言
ManualResetEvent 是 C# 中用于线程同步的核心类之一位于 System.Threading 命名空间下。它的核心功能是通过信号机制控制线程的执行顺序允许一个或多个线程等待某个信号后再继续运行。与 AutoResetEvent 不同ManualResetEvent 在被触发后会保持信号状态直到显式地调用 Reset() 方法将其重置为非信号状态。这种特性使得它适用于需要广播多个线程的场景。 一、核心概念
作用通过信号机制控制线程的执行允许一个或多个线程等待某个事件完成。信号状态 有信号Signaled所有调用 WaitOne() 的线程不会被阻塞。无信号Non-signaled所有调用 WaitOne() 的线程会被阻塞直到调用 Set()。 手动重置 调用 Set() 后事件保持有信号状态需显式调用 Reset() 才能恢复无信号状态。意味着可以释放多个等待的线程。 本文中所描述的 有信号状态、终止状态、触发状态 意义相同都是同一种状态的不同名称 二、基本用法
1. 构造函数
var manualEvent new ManualResetEvent(initialState: false); // 初始无信号initialState初始化是否为有信号状态true 表示有信号/或称 已触发则线程一开始是无需等待信号的。
2. 关键方法
方法作用Set()将事件设为有信号状态释放所有等待线程。Reset()将事件设为无信号状态后续的 WaitOne() 会阻塞。WaitOne()阻塞当前线程直到事件变为有信号状态。可以指定超时时间Dispose()释放资源继承自 WaitHandle。
三、 示例
示例 1单线程等待事件
using System.Threading;class Program
{static ManualResetEvent manualEvent new ManualResetEvent(false);static void Main(){Thread worker new Thread(DoWork);worker.Start();// 主线程触发信号Thread.Sleep(2000);Console.WriteLine(主线程发送信号);manualEvent.Set(); // 释放工作线程}static void DoWork(){Console.WriteLine(工作线程等待信号...);manualEvent.WaitOne(); // 阻塞直到信号触发Console.WriteLine(工作线程继续执行);}
}输出
工作线程等待信号...
主线程发送信号
工作线程继续执行示例 2广播多个线程
static ManualResetEvent manualEvent new ManualResetEvent(false);static void Main()
{// 启动3个等待线程for (int i 0; i 3; i){new Thread(() {manualEvent.WaitOne();Console.WriteLine($线程 {Thread.CurrentThread.ManagedThreadId} 被唤醒);}).Start();}// 主线程触发广播Thread.Sleep(2000);manualEvent.Set(); // 所有等待线程同时释放manualEvent.Reset(); // 重置为无信号后续新线程需要重新等待
}输出
线程 4 被唤醒
线程 5 被唤醒
线程 6 被唤醒四、与 AutoResetEvent 的区别
1. 区别
特性ManualResetEventAutoResetEvent重置方式需显式调用 Reset()调用 Set() 后自动重置唤醒线程数量唤醒所有等待线程每次 Set() 仅唤醒一个线程适用场景广播通知如初始化完成、批量任务开始严格交替执行如生产者-消费者模型
2. 示例
AutoResetEvent 示例
class Program
{// 线程通知private static AutoResetEvent resetEvent new AutoResetEvent(false);static void Main(string[] args){// 创建线程Thread worker new Thread(DoWork);worker.Start();// 用于不断向另一个线程发送信号while (true){Console.ReadKey();resetEvent.Set(); // 按下任意键将事件设为有信号状态释放等待线程。}}public static void DoWork(){Console.WriteLine(① 等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(② 等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(③ 等待中请发出信号允许我运行);// ...Console.WriteLine(线程结束);}
}输出按下任意键按一下输出一下内容
① 等待中请发出信号允许我运行
② 等待中请发出信号允许我运行
③ 等待中请发出信号允许我运行
线程结束ManualResetEvent 示例
class Program
{private static ManualResetEvent resetEvent new ManualResetEvent(false);static void Main(string[] args){// 创建线程Thread worker new Thread(DoWork);worker.Start();// 用于不断向另一个线程发送信号while (true){Console.ReadKey();resetEvent.Set(); // 按下任意键将事件设为有信号状态释放【所有】等待线程。}}public static void DoWork(){Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();// 后面的都无效线程会直接跳过而无需等待Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(等待中请发出信号允许我运行);resetEvent.WaitOne();Console.WriteLine(线程结束);}
}输出按下任意键直接输出所有内容
等待中请发出信号允许我运行
等待中请发出信号允许我运行
等待中请发出信号允许我运行
等待中请发出信号允许我运行
等待中请发出信号允许我运行
等待中请发出信号允许我运行
线程结束AutoResetEvent 在 WaitOne() 方法等待信号完毕后会自动重置为无信号状态相当于高速收费站自动闸门一辆车过去后机器自动关闸。 ManualResetEvent 相当于人工闸门打开后需要人工关闭闸门不然的话闸门会一直处于打开状态。 ManualResetEvent 主要用于更加灵活的线程信号传递场景。
五、高级用法
1. 超时等待
bool signaled manualEvent.WaitOne(TimeSpan.FromSeconds(3));
if (!signaled)
{Console.WriteLine(等待超时);
}六、注意事项
1. 资源释放
使用 Dispose() 或 using 块释放资源避免句柄泄漏。
using (var manualEvent new ManualResetEvent(false))
{// 使用 manualEvent
}2. 避免死锁
确保 Set() 和 Reset() 的调用逻辑合理避免线程永久阻塞。示例忘记调用 Set() 或 Reset()。
3. 线程安全
多线程环境下确保对 Set() 和 Reset() 的调用是线程安全的。
七、替代方案
ManualResetEventSlim轻量级版本性能更高适合短期等待。Semaphore/SemaphoreSlim控制并发线程数量。TaskCompletionSource基于任务的异步模式TAP。
八、常见问题
1. 问题忘记调用 Reset()
现象Set() 后事件保持有信号状态后续所有 WaitOne() 直接通过。解决在需要重新阻塞线程前调用 Reset()。
2. 问题多次调用 Set()
现象无影响事件已处于有信号状态时Set() 不会改变状态。 结语
回到目录页C#/.NET 知识汇总 希望以上内容可以帮助到大家如文中有不对之处还请批评指正。 参考资料 ManualResetEvent的使用 C# ManualResetEvent 类的用法 C#学习二十八——ManualResetEvent的理解和使用 手动线程通知 ManualResetEvent