参考链接:https://blog.csdn.net/bluecard2008/article/details/80106770
    bluecard2008 最后发布于2018-04-27 13:31:32 阅读数 676

    一、两者区别
    1.ManualResetEvent 调用一次Set()后将允许恢复所有被阻塞线程。需手动在调用WaitOne()之后调用Reset()重置信号量状态为非终止,然后再次调用WaitOne()的时候才能继续阻塞线程,反之则不阻塞
    2.AutoResetEvent,调用一次Set()只能继续被阻塞的一个线程,多次调用Set()才行,但不需手动调用Reset();再次调用WaitOne()的时候又能阻塞线程,也是和前者的区别
    3.两者单个实例均可阻塞一个或多个线程,在多个线程中调用 主线程 创建的 两者单个实例.WaitOne(),前提是两者实例必须是非终止状态
    4.两者实例化构造参数解释
    public AutoResetEvent(bool initialState);
    true:设置终止状态。相当于调用了Set(),即首次不会被WaitOne()阻塞,下次执行WaitOne()才会被阻塞
    false:设置非终止状态。遇到WaitOne()立即阻塞所在的一个或多个线程
    5. 两者都只会阻塞WaitOne()所在的线程,WaitOne()可被多个线程调用

    二、在哪里创建信号量实例?
    一般情况下在工作线程中创建信号量的实例,在其他线程中使用,然后再在工作线程中调用Set(),可以是在非主线程创建实例

    三、代码示例

    1. public class Program
    2. {
    3. //1.AutoResetEvent,调用一次Set()只能继续一个阻塞线程
    4. //2.AutoResetEvent调用Set()后自动Reset()
    5. static void Main(string[] args)
    6. {
    7. Thread t = null;
    8. AutoResetEvent Event = new AutoResetEvent(false);
    9. for (int i = 0; i < 2; i++)
    10. {
    11. t = new Thread(() =>
    12. {
    13. while (true)
    14. {
    15. //阻塞当前线程
    16. Event.WaitOne();
    17. Console.WriteLine("我是线程:" + Thread.CurrentThread.Name);
    18. Thread.Sleep(1000);
    19. }
    20. });
    21. t.Name = i + "";
    22. t.Start();
    23. }
    24. //5秒后允许一个等待的线程继续。当前允许的是线程1
    25. Thread.Sleep(5000);
    26. Event.Set();
    27. //5秒后允许一个等待的线程继续。当前允许的是线程2
    28. Thread.Sleep(5000);
    29. Event.Set();
    30. //PS:如果使用AutoResetEvent的WaitOne()将5个线程阻塞,则需要调用5次Set()才能恢复5;如果再次阻塞时,不需要手动调用Reset();
    31. Console.ReadLine();
    32. }
    33. //1.ManualResetEvent,调用一次Set()允许继续全部阻塞线程,这是和AutoResetEvent的区别
    34. //2.ManualResetEvent调用Set()后需要手动Reset(),将信号 设置为非终止状态,只有非终止状态线程中调用WaitOne()才能导所在的致线程阻止。
    35. static void Main2(string[] args)
    36. {
    37. Thread t = null;
    38. //初始化非终止状态,WaitOne()可以直接阻塞所在的线程
    39. ManualResetEvent Event = new ManualResetEvent(false);
    40. for (int i = 0; i < 2; i++)
    41. {
    42. t = new Thread(() =>
    43. {
    44. while (true)
    45. {
    46. //阻塞当前线程
    47. Event.WaitOne();
    48. Console.WriteLine("我是线程:" + Thread.CurrentThread.Name);
    49. Event.ReSet();
    50. Thread.Sleep(1000);
    51. }
    52. });
    53. t.Name = i + "";
    54. t.Start();
    55. }
    56. //5秒后允许所有阻塞的线程继续。
    57. Thread.Sleep(5000);
    58. Event.Set();
    59. //PS:如果使用ManualResetEvent将5个线程阻塞,则需要调用1次Set(),将允许所有阻塞的线程继续执行;如果再次阻塞时,则需要手动调用Reset();
    60. Console.ReadLine();
    61. }
    62. }