1. 类的关系

  1. AutoResetEvent 和 ManualResetEvent 都继承自 System.Threading.EventWaitHandle 类(EventWaitHandle 继承自 WaitHandle);
  2. 用于线程交互 (或线程信号)

2. 常用方法

2.1 WaitHandle 几个常用的方法

  1. public virtual bool WaitOne(int millisecondsTimeout); //阻止当前线程 ,直到当前 System.Threading.WaitHandle 收到信号,或直到 millisecondsTimeout 后。
  2. public virtual bool WaitOne(); //阻止当前线程,直到当前 System.Threading.WaitHandle 收到信号。
  3. public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout);
  4. public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout);

2.2 EventWaitHandle 几个常用的方法

  1. public bool Set();

    将事件设置为有信号,从而允许一个或多个等待线程继续执行
  2. public bool Reset();

    将事件设置为非终止状态,从而导致线程受阻

2.3 AutoResetEvent

  1. 该类的定义:通知正在等待的线程已发生事件
  2. public AutoResetEvent(bool initialState); //initialState 指是否将初始状态设置为终止状态的类

2.4 ManualResetEvent

  1. 该类的定义:通知一个或多个正在等待的线程已发生事件
  2. public ManualResetEvent(bool initialState);

3. 使用逻辑

3.1 AutoResetEvent 的使用逻辑

  1. 实例化 AutoResetEvent 时,需要设置初始状态是否为终止状态;
  2. 若遇到状态为非终止状态的 AutoResetEvent 的 Wait 系列方法(如 WaitOne()),将 阻止当前线程继续往下执行,直到当前 AutoResetEvent 收到信号;
  3. 收到信号后,保持终止状态并释放一个等待线程,让其继续往下执行,然后自动返回非终止状态。

3.2 ManualResetEvent 的使用逻辑

  1. 实例化 ManualResetEvent 时,需要设置初始状态是否为终止状态;
  2. 若遇到状态为非终止状态的 ManualResetEvent 的 Wait 系列方法(如 WaitOne()),将 阻止当前线程继续往下执行,直到当前 ManualResetEvent 收到信号;
  3. 收到信号后,所有等待线程都被释放,可以继续往下执行;
  4. 跟 AutoResetEvent 不同的是,收到信号后,ManualResetEvent 将继续保持信号,直到通过手动调用 Reset() 方法重置 ManualResetEvent 的状态为非终止。

4. 例子

4.1 AutoResetEvent

using System;
using System.Threading; class Example
{
private static AutoResetEvent event_1 = new AutoResetEvent(true);
private static AutoResetEvent event_2 = new AutoResetEvent(false); static void Main()
{
for (int i = 1; i < 4; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(250); for (int i = 0; i < 2; i++)
{
Console.WriteLine("按任意键释放另一个线程");
Console.ReadLine();
event_1.Set();
Thread.Sleep(250);
} Console.WriteLine("\r\n至此所有线程都在等待 AutoResetEvent #2."); for (int i = 0; i < 3; i++)
{
Console.WriteLine("按任意键释放另一个线程");
Console.ReadLine();
event_2.Set();
Thread.Sleep(250);
}
} static void ThreadProc()
{
string name = Thread.CurrentThread.Name; Console.WriteLine("{0} 等待 AutoResetEvent #1.", name);
event_1.WaitOne();
Console.WriteLine("{0} 被 AutoResetEvent #1 释放.", name); Console.WriteLine("{0} 等待 AutoResetEvent #2.", name);
event_2.WaitOne();
Console.WriteLine("{0} 被 from AutoResetEvent #2 释放.", name); Console.WriteLine("{0} 结束.", name);
}
} /* 上面例子将输出如下: Thread_1 等待 AutoResetEvent #1.
Thread_1 被 AutoResetEvent #1 释放.
Thread_1 等待 AutoResetEvent #2.
Thread_2 等待 AutoResetEvent #1.
Thread_3 等待 AutoResetEvent #1.
按任意键释放另一个线程 Thread_2 被 AutoResetEvent #1 释放.
Thread_2 等待 AutoResetEvent #2.
按任意键释放另一个线程 Thread_3 被 AutoResetEvent #1 释放.
Thread_3 等待 AutoResetEvent #2. 至此所有线程都在等待 AutoResetEvent #2.
按任意键释放另一个线程. Thread_1 被 from AutoResetEvent #2 释放.
Thread_1 结束.
按任意键释放另一个线程. Thread_2 被 from AutoResetEvent #2 释放.
Thread_2 结束.
按任意键释放另一个线程. Thread_3 被 from AutoResetEvent #2 释放.
Thread_3 结束.
*/

4.2 ManualResetEvent

using System;
using System.Threading; public class Example
{
private static ManualResetEvent mre = new ManualResetEvent(false); static void Main()
{
Console.WriteLine("\n开启 3 个被 ManualResetEvent 阻塞的线程\n"); for (int i = 0; i <= 2; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
} Thread.Sleep(500);
Console.WriteLine("\n所有线程已开启,请按下 enter 键发送信号从而一次性释放所有线程\n");
Console.ReadLine(); mre.Set(); Thread.Sleep(500); // 主线程等待 500 毫秒让子线程先执行完毕 Console.WriteLine("\n当 ManualResetEvent 是有信号时,即使遇到 WaitOne() 也不会被阻塞:\n"); for (int i = 3; i <= 4; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
} Thread.Sleep(500);
Console.WriteLine("\n请按下 enter 键盘触发 Reset() 方法, 从而后面的线程在遇到 WaitOne() 时继续被阻塞.\n");
Console.ReadLine(); mre.Reset(); Thread t5 = new Thread(ThreadProc);
t5.Name = "Thread_5";
t5.Start(); Thread.Sleep(500);
Console.WriteLine("\n请按下 enter 键发送信号.");
Console.ReadLine(); mre.Set(); Console.ReadLine();
} private static void ThreadProc()
{
string name = Thread.CurrentThread.Name; Console.WriteLine(name + " starts and calls mre.WaitOne()"); mre.WaitOne(); Console.WriteLine(name + " ends.");
}
} /* 上面例子将输出如下: 开启 3 个被 ManualResetEvent 阻塞的线程 Thread_0 starts and calls mre.WaitOne()
Thread_1 starts and calls mre.WaitOne()
Thread_2 starts and calls mre.WaitOne() 所有线程已开启,请按下 enter 键发送信号从而一次性释放所有线程 Thread_0 ends.
Thread_1 ends.
Thread_2 ends. 当 ManualResetEvent 是有信号时,即使遇到 WaitOne() 也不会被阻塞: Thread_3 starts and calls mre.WaitOne()
Thread_3 ends.
Thread_4 starts and calls mre.WaitOne()
Thread_4 ends. 请按下 enter 键盘触发 Reset() 方法, 从而后面的线程在遇到 WaitOne() 时继续被阻塞. Thread_5 starts and calls mre.WaitOne() 请按下 enter 键发送信号. Thread_5 ends.
*/

最新文章

  1. Java中图片压缩处理
  2. MyBatis Generator自动生成的配置及使用
  3. codeforces round #201 Div2 A. Difference Row
  4. paper 4:支持向量机系列一: Maximum Margin Classifier —— 支持向量机简介。
  5. Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径
  6. A. Sorting Railway Cars
  7. Objective-C 【单个对象内存管理(野指针&amp;内存泄露)】
  8. ORA-12154 TNS无法解析指定的连接标识符
  9. eclipse 修改设置Ctrl+Shift+F长度
  10. 想加入一行代码吗?使用&lt;code&gt;标签
  11. ASP.Net动态创建GridView
  12. jquery中当CheckBoxList被选中时提示
  13. struts2之数据校验
  14. 【iCore4 双核心板_FPGA】例程十六:基于双口RAM的ARM+FPGA数据存取实验
  15. Python使用xml.dom解析xml
  16. windows composer 安装,使用新手入门
  17. 获取页面所有链接的JS
  18. virtualbox+vagrant学习-2(command cli)-14-vagrant reload命令
  19. 【JavaScript】闭包应用之数据独立
  20. springCloud3---ribbon

热门文章

  1. 逆元 exgcd 费马小定理 中国剩余定理的理解和证明
  2. 还傻傻分不清楚equals和==的区别吗?看完就明白了
  3. 在利用手背扫描图像+K因子 对室内温度进行回归预测时碰到的问题
  4. node.js cli downloader
  5. Flow All In One
  6. HTTPS All In One
  7. Axios 取消 Ajax 请求
  8. ESLint &amp; .eslintignore
  9. macOS 录屏 gif
  10. HDFS 01 - HDFS是什么?它的适用场景有哪些?它的架构是什么?