AutoReSetEvent用法(二)

来源:互联网 发布:java实参和形参的传递 编辑:程序博客网 时间:2024/05/16 11:03

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading;  
  6.   
  7. namespace ConsoleTest  
  8. {  
  9.     //下面代码说明在进程等待后台线程执行完时,如何使用等待句柄阻止进程终止。  
  10.     class Program  
  11.     {  
  12.         static AutoResetEvent autoEvent = new AutoResetEvent(false);  
  13.   
  14.         static void Main(string[] args)  
  15.         {  
  16.             Console.WriteLine("Main starting.");  
  17.   
  18.             ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod), autoEvent);  
  19.   
  20.             //if (autoEvent.WaitOne(1000, false))  
  21.             //    Console.WriteLine("Work method signaled.");  
  22.             //else  
  23.             //    Console.WriteLine("Time out waiting for work "+"method to signal.");  
  24.   
  25.             //Wait for work method to signal.  
  26.             autoEvent.WaitOne();  
  27.   
  28.             Console.WriteLine("Main ending.");  
  29.         }  
  30.   
  31.         static void WorkMethod(object stateInfo)  
  32.         {  
  33.             Console.WriteLine("Work starting.");  
  34.             Thread.Sleep(new Random().Next(100, 2000));  
  35.             Console.WriteLine("Work ending.");  
  36.             ((AutoResetEvent)stateInfo).Set();  
  37.         }  
  38.     }  
  39. }  

执行结果:

Main starting.
Work starting.
Work ending.
Main ending.

 

WaitOne:在一个线程MainThread中开启一个新的线程NewThread,在完成初始化并启动NewThread的操作后,调用WaitOne,则MainThread堵塞,直到在NewThread中调用Set,MainThread才继续执行。

 

 

AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。

线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set 发出资源可用的信号。

调用 Set 向 AutoResetEvent 发信号以释放等待线程。AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待,则状态将无限期地保持为终止状态。

可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为终止状态,则为true;否则为 false

通俗的来讲只有等myResetEven.Set()成功运行后,myResetEven.WaitOne()才能够获得运行机会;Set是发信号,WaitOne是等待信号,只有发了信号,等待的才会执行。如果不发的话,WaitOne后面的程序就永远不会执行。

 

下面我们来举一个例子:我去书店买书,当我选中一本书后我会去收费处付钱,
付好钱后再去仓库取书。这个顺序不能颠倒,我作为主线程,收费处和仓库做两个辅助线程,代码如下:

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading;  
  6.   
  7. namespace AutoResetEventDemo  
  8. {  
  9.     class Program  
  10.     {  
  11.         const int num = 550;  
  12.         static AutoResetEvent myResetEvent = new AutoResetEvent(false);  
  13.         static AutoResetEvent changeEvent = new AutoResetEvent(false);  
  14.         static int number;//这是关键资源  
  15.   
  16.         static void PayMoneyProc()  
  17.         {  
  18.             while (true)  
  19.             {  
  20.                 myResetEvent.WaitOne();  
  21.                 Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);  
  22.             }  
  23.         }  
  24.   
  25.         static void GetBookProc()  
  26.         {  
  27.             while (true)  
  28.             {  
  29.                 changeEvent.WaitOne();  
  30.                 Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);  
  31.                 Console.WriteLine("------------------------------");  
  32.                 Thread.Sleep(0);  
  33.             }  
  34.         }  
  35.   
  36.         static void Main()  
  37.         {  
  38.             Thread payMoneyThread = new Thread(new ThreadStart(PayMoneyProc));  
  39.             payMoneyThread.Name = "付钱线程";  
  40.             Thread getBookThread = new Thread(new ThreadStart(GetBookProc));  
  41.             getBookThread.Name = "取书线程";  
  42.             payMoneyThread.Start();  
  43.             getBookThread.Start();  
  44.   
  45.             for (int i = 1; i < num; i++)  
  46.             {  
  47.                 Console.WriteLine("买书线程:数量{0}",i);  
  48.                 number = i;  
  49.                 myResetEvent.Set();  
  50.                 changeEvent.Set();  
  51.                 Thread.Sleep(0);  
  52.             }  
  53.   
  54.             payMoneyThread.Abort();//调用此方法通常会终止线程  
  55.             getBookThread.Abort();  
  56.         }  
  57.     }  
  58. }  

0
0 0