灵活使用多线程编程——AutoResetEvent类(转)
时间:2011-02-25 来源:董雨
该类的作用是通知正在等待的线程已发生的事件。该类存在于mscorlib.DLL中。
在.Net Framework 2.0中,该类是继承自EventWaitHalder,AutoResetEvent在功效上等同于 EventResetModel.AutoReset创建的EventWaitHandle。下面我们反编译该类的代码,下边为该类得构造函数的代码:
1 [ComVisible(true), HostProtection(SecurityAction.LinkDemand, Synchronization=true, ExternalThreading=true)]
2 public sealed class AutoResetEvent : EventWaitHandle
3 {
4 // Methods
5 [SecuritySafeCritical]
6 public AutoResetEvent(bool initialState) : base(initialState, EventResetMode.AutoReset)
7 {
8 }
9 }
10
11
AutoResetEvent是允许线程通过发信号进行互相通信访问的。通常,此类通信涉及线程需要独占访问资源。
线程通过调用AutoResetEvent上的WaitOne来等待信号,如果AutoResetEvent处于非终止状态的话,则该线程阻塞,并且等待当前控制资源的线程通过调用Set发出资源可用信号。
调用Set向AutoResetEvent发出信号以释放等待的线程,AutoResetEvent将处于终止状态,直到一个等待的线程释放,然后自动返回非终止状态,如果没有任何线程在等待,则该信号无限期的保持在终止状态。
可以通过将一个Bool值传给AutoResetEvent的构造函数,用于设置是否为非终止状态。如果传入的为TRUE,则初始状态为终止状态,否则为FALSE。
下面我们通过一个示例来详细说明该类的用法:
Code1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Threading;
10
11 namespace WindowsFormsApplication2
12 {
13 public partial class Form2 : Form
14 {
15 /// <summary>
16 /// 第一次计算的结果
17 /// </summary>
18 double firstNumber = 0;
19 /// <summary>
20 /// 第二次计算的结果
21 /// </summary>
22 double secondNumber = 0;
23 /// <summary>
24 /// 第三次计算的结果
25 /// </summary>
26 double thirdNumber = 0;
27
28 /// <summary>
29 /// 三次计算对应的线程等待变量
30 /// </summary>
31 AutoResetEvent[] autoResetEvent = null;
32
33 /// <summary>
34 /// 随机变量种子
35 /// </summary>
36 Random random = null;
37
38 public Form2()
39 {
40 InitializeComponent();
41
42 //初始设置为非终止状态,此时三个变量均处于阻塞状态
43 autoResetEvent = new AutoResetEvent[]{
44 new AutoResetEvent(false),
45 new AutoResetEvent(false),
46 new AutoResetEvent(false)
47 };
48 }
49
50 private void button1_Click(object sender, EventArgs e)
51 {
52 MessageBox.Show(SimuValue(Int32.Parse(this.textBox1.Text)).ToString());
53 }
54
55 /// <summary>
56 /// 计算第一个数值
57 /// </summary>
58 /// <param name="stateInfo"></param>
59 void SimuFirstNumber(object stateInfo)
60 {
61 double v = random.NextDouble();
62 double p = random.NextDouble();
63
64 firstNumber = v * p;
65
66 //发出变量将该事件状态设置为终止状态,允许一个或多个等待线程继续
67 autoResetEvent[0].Set();
68 }
69 /// <summary>
70 /// 计算第二个数值
71 /// </summary>
72 /// <param name="stateInfo"></param>
73 void SimuSecondNumber(object stateInfo)
74 {
75 double v = random.NextDouble();
76 double p = random.NextDouble();
77
78 secondNumber = v * p;
79
80 autoResetEvent[1].Set();
81 }
82 /// <summary>
83 /// 计算第三个数值
84 /// </summary>
85 /// <param name="stateInfo"></param>
86 void SimuThirdNumber(object stateInfo)
87 {
88 double v = random.NextDouble();
89 double p = random.NextDouble();
90
91 thirdNumber = v * p;
92
93 autoResetEvent[2].Set();
94 }
95
96 /// <summary>
97 /// 计算所有的数值乘积
98 /// </summary>
99 /// <param name="v"></param>
100 double SimuValue(int v)
101 {
102 random = new Random(v);
103
104 //调用多线程计算三个数值
105 ThreadPool.QueueUserWorkItem(new WaitCallback(SimuFirstNumber));
106 ThreadPool.QueueUserWorkItem(new WaitCallback(SimuSecondNumber));
107 ThreadPool.QueueUserWorkItem(new WaitCallback(SimuThirdNumber));
108
109 //等到三个线程计算完毕
110 WaitHandle.WaitAll(autoResetEvent);
111
112 return firstNumber * secondNumber * thirdNumber;
113 }
114 }
115 }
116
AutoResetEvent中比较有用的函数分别为以下几个:
1.Set() 将事件的状态位置设置为终止状态,允许一个或多个等待线程继续。
2.ReSet()将事件的状态设置为非终止状态,阻塞该线程。
3.WaitOne()阻止当前线程。直到当前WaitHandle收到信号。