zoukankan      html  css  js  c++  java
  • 使用AutoResetEvent,ManualResetEvent和ManualResetEventSlim类进行线程间通信

     AutoResetEvent和ManualResetEvent允许线程通过发信号进行通信。

     两者都有两个信号量:True和False。都通过Set()和ReSet()来设置。并且使用WaitOne()的方法阻止当前的线程。

     不同的是AutoResetEvent在调用Set()把信号量释放后(信号量设置为True),然后自动返回到终止状态(信号量为False). 

     线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 AutoResetEvent 为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用 Set 来通知资源可用。
     调用 Set 向 AutoResetEvent 发信号以释放等待线程。 AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。 如果没有任何线程在等待,则状态将无限期地保持为终止状态。
    如果当 AutoResetEvent 为终止状态时线程调用 WaitOne,则线程不会被阻止。 AutoResetEvent 将立即释放线程并返回到未触发状态。

     ManualResetEvent在调用Set()后,需要手动调用ReSet()恢复到终止状态。

     ManualResetEventSlim是ManualResetEvent的简化版本,是4.0新增的类。使用Wait()方法来阻止线程。

     MSDN上的代码很好的解释了如何使用:

     Code:

    使用AutoResetEvent 

     1    class Example
     2     {
     3         private static AutoResetEvent event_1 = new AutoResetEvent(true); 
     4         private static AutoResetEvent event_2 = new AutoResetEvent(false);
     5 
     6         static void Main()
     7         {
     8             Console.WriteLine("Press Enter to create three threads and start them.
    " +
     9                               "The threads wait on AutoResetEvent #1, which was created
    " +
    10                               "in the signaled state, so the first thread is released.
    " +
    11                               "This puts AutoResetEvent #1 into the unsignaled state.");
    12             Console.ReadLine();
    13 
    14             for (int i = 1; i < 4; i++)
    15             {
    16                 Thread t = new Thread(ThreadProc);
    17                 t.Name = "Thread_" + i;
    18                 t.Start();
    19             }
    20             Thread.Sleep(1000);
    21 
    22             for (int i = 0; i < 2; i++)
    23             {
    24                 Console.WriteLine("Press Enter to release another thread.");
    25                 Console.ReadLine();
    26                 event_1.Set();
    27                 Thread.Sleep(250);
    28             }
    29 
    30             Console.WriteLine("
    All threads are now waiting on AutoResetEvent #2.");
    31             for (int i = 0; i < 3; i++)
    32             {
    33                 Console.WriteLine("Press Enter to release a thread.");
    34                 Console.ReadLine();
    35                 event_2.Set();
    36                 Thread.Sleep(250);
    37             }
    38 
    39             // Visual Studio: Uncomment the following line.
    40             //Console.Readline();
    41         }
    42 
    43         static void ThreadProc()
    44         {
    45             string name = Thread.CurrentThread.Name;
    46 
    47             Console.WriteLine("{0} waits on AutoResetEvent #1.", name);
    48             event_1.WaitOne();
    49             Console.WriteLine("{0} is released from AutoResetEvent #1.", name);
    50 
    51             Console.WriteLine("{0} waits on AutoResetEvent #2.", name);
    52             event_2.WaitOne();
    53             Console.WriteLine("{0} is released from AutoResetEvent #2.", name);
    54 
    55             Console.WriteLine("{0} ends.", name);
    56         }
    57     }
    View Code

    使用ManualResetEvent

     1    public class Example
     2     {
     3         private static ManualResetEvent mre = new ManualResetEvent(false);
     4 
     5         static void Main()
     6         {
     7             Console.WriteLine("
    Start 3 named threads that block on a ManualResetEvent:
    ");
     8 
     9             for (int i = 0; i <= 2; i++)
    10             {
    11                 Thread t = new Thread(ThreadProc);
    12                 t.Name = "Thread_" + i;
    13                 t.Start();
    14             }
    15 
    16             Thread.Sleep(500);
    17             Console.WriteLine("
    When all three threads have started, press Enter to call Set()" +
    18                               "
    to release all the threads.
    ");
    19             Console.ReadLine();
    20 
    21             mre.Set();
    22 
    23             Thread.Sleep(500);
    24             Console.WriteLine("
    When a ManualResetEvent is signaled, threads that call WaitOne()" +
    25                               "
    do not block. Press Enter to show this.
    ");
    26             Console.ReadLine();
    27 
    28             for (int i = 3; i <= 4; i++)
    29             {
    30                 Thread t = new Thread(ThreadProc);
    31                 t.Name = "Thread_" + i;
    32                 t.Start();
    33             }
    34 
    35             Thread.Sleep(500);
    36             Console.WriteLine("
    Press Enter to call Reset(), so that threads once again block" +
    37                               "
    when they call WaitOne().
    ");
    38             Console.ReadLine();
    39 
    40             mre.Reset();
    41 
    42             // Start a thread that waits on the ManualResetEvent.
    43             Thread t5 = new Thread(ThreadProc);
    44             t5.Name = "Thread_5";
    45             t5.Start();
    46 
    47             Thread.Sleep(500);
    48             Console.WriteLine("
    Press Enter to call Set() and conclude the demo.");
    49             Console.ReadLine();
    50 
    51             mre.Set();
    52 
    53             // If you run this example in Visual Studio, uncomment the following line:
    54             //Console.ReadLine();
    55         }
    56 
    57         private static void ThreadProc()
    58         {
    59             string name = Thread.CurrentThread.Name;
    60 
    61             Console.WriteLine(name + " starts and calls mre.WaitOne()");
    62 
    63             mre.WaitOne();
    64 
    65             Console.WriteLine(name + " ends.");
    66         }
    67     }
    View Code

    使用ManualResetEventSlim

     1    class MRESDemo
     2     {
     3         static void Main()
     4         {
     5             MRES_SetWaitReset();
     6             MRES_SpinCountWaitHandle();
     7             Console.ReadKey();
     8         }
     9         static void MRES_SetWaitReset()
    10         {
    11             ManualResetEventSlim mres1 = new ManualResetEventSlim(false); // initialize as unsignaled
    12             ManualResetEventSlim mres2 = new ManualResetEventSlim(false); // initialize as unsignaled
    13             ManualResetEventSlim mres3 = new ManualResetEventSlim(true);  // initialize as signaled
    14 
    15             var observer = Task.Factory.StartNew(() =>
    16             {
    17                 mres1.Wait();
    18                 Console.WriteLine("observer sees signaled mres1!");
    19                 Console.WriteLine("observer resetting mres3...");
    20                 mres3.Reset(); 
    21                 Console.WriteLine("observer signalling mres2");
    22                 mres2.Set();
    23             });
    24             Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet);
    25             Console.WriteLine("main thread signalling mres1");
    26             mres1.Set();
    27             mres2.Wait();
    28 
    29             Console.WriteLine("main thread sees signaled mres2!");
    30             Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet);
    31 
    32             observer.Wait(); // make sure that this has fully completed
    33             mres1.Dispose();
    34             mres2.Dispose();
    35             mres3.Dispose();
    36         }
    37 
    38         static void MRES_SpinCountWaitHandle()
    39         {
    40             // Construct a ManualResetEventSlim with a SpinCount of 1000
    41             // Higher spincount => longer time the MRES will spin-wait before taking lock
    42             ManualResetEventSlim mres1 = new ManualResetEventSlim(false, 1000);
    43             ManualResetEventSlim mres2 = new ManualResetEventSlim(false, 1000);
    44 
    45             Task bgTask = Task.Factory.StartNew(() =>
    46             {
    47                 Thread.Sleep(100);
    48                 Console.WriteLine("Task signalling both MRESes");
    49                 mres1.Set();
    50                 mres2.Set();
    51             });
    52 
    53             WaitHandle.WaitAll(new WaitHandle[] { mres1.WaitHandle, mres2.WaitHandle });
    54             Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.");
    55 
    56             bgTask.Wait();
    57             mres1.Dispose();
    58             mres2.Dispose();
    59         }
    60     }
    View Code
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/mandel/p/3579569.html
Copyright © 2011-2022 走看看