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
  • 相关阅读:
    java大数取余
    hdu--5351--MZL's Border
    NYOJ--水池数目
    NYOJ--32--SEARCH--组合数
    NYOJ--20--搜索(dfs)--吝啬的国度
    hdu--4148--Length of S(n)
    hdu--2098--分拆素数和
    hdu--1873--看病要排队
    hdu--1870--愚人节的礼物
    hdu--1237--简单计算器
  • 原文地址:https://www.cnblogs.com/mandel/p/3579569.html
Copyright © 2011-2022 走看看