.NET中线程同步相关的一些类
WaitHandle
===========
包装了为了共享某一资源而对排他访问进行等待的特定的操作系统对象.
该对象是典型地用作同步对象的基类. 从WaitHandle派生出来的类们定义了一个信号机制, 用于表示占有或释放对于一个共享资源的而访问, 但是它们使用继承而来的WaitHandle的方法来在需要等待访问共享资源的的时候阻塞自己.
WaitHandle.WaitOne方法, 作用是阻塞住当前线程, 直到当前的WaitHandle收到信号为止.
使用这个类的静态方法来阻塞一个线程直到一个或多个synchronization对象收到了信号. 具体的代码例子, 下面的原文出处中有.
摘自:
http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx
ThreadPool.QueueUserWorkItem方法
================
将一个用于执行的方法添加到队列中. 这个方法会在线程池中有可用的线程时被执行.
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx
WaitCallback代理
================
代表着被线程池中的线程执行的一个回调方法.
用法如下:
1: using System;
2: using System.Threading;
3: public class Example {
4: public static void Main() {
5: // Queue the task.
6: ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
7:
8: Console.WriteLine("Main thread does some work, then sleeps.");
9: // If you comment out the Sleep, the main thread exits before
10: // the thread pool task runs. The thread pool uses background
11: // threads, which do not keep the application running. (This
12: // is a simple example of a race condition.)
13: Thread.Sleep(1000);
14:
15: Console.WriteLine("Main thread exits.");
16: }
17:
18: // This thread procedure performs the task.
19: static void ThreadProc(Object stateInfo) {
20: // No state object was passed to QueueUserWorkItem, so
21: // stateInfo is null.
22: Console.WriteLine("Hello from the thread pool.");
23: }
24: }
http://msdn.microsoft.com/en-us/library/system.threading.waitcallback.aspx
AutoResetEvent
===================
System..::.Object
System..::.MarshalByRefObject
System.Threading..::.WaitHandle
System.Threading..::.EventWaitHandle
System.Threading..::.AutoResetEvent
通知一个等待的线程, 告诉它一个事件已经发生了.
线程通过在AutoResetEvent上调用WaitOne方法来等待一个信号. 如果AutoResetEvent处于无信号状态, 线程阻塞, 等待当前控制资源的线程来放出信号告诉它这个资源已经可用了, 放信号的方法是调用Set方法.
Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely.
If a thread calls WaitOne while the AutoResetEvent is in the signaled state, the thread does not block. The AutoResetEvent releases the thread immediately and returns to the non-signaled state.
EventWaitHandle的Set方法
Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
ManualResetEvent
===========
继承树:
System..::.Object
System..::.MarshalByRefObject
System.Threading..::.WaitHandle
System.Threading..::.EventWaitHandle
System.Threading..::.ManualResetEvent
该类的作用是, 通知一个或更多的线程: 一个事件发生了.
ManualresetEvent允许线程彼此使用信号方式进行通信. 典型地, 这个通信过程与这样的一个任务有关: 该任务在某一个线程中必须先完成, 另一个线程才可以继续.
当一个线程开始了一个那种它完成之后别的线程才可以继续执行的动作时, 它调用Reset方法来让ManualResetEvent进入到一个无信号(non-signaled)状态. 这个线程可以被看作是在控制ManualResetEvent. 在ManualresetEvent上调用WaitOne的线程会被阻塞, 等待信号到来. 当控制者线程完成了动作, 它会调用Set方法来告诉等待的线程他们可以继续了. 所有等待的线程就都被释放掉了.
一旦他被信号通知了, ManualResetEvent仍然保持着signaled的状态, 知道它被手动地reset. 也就是说, 调用WaitOne会迅速返回.
You can control the initial state of a ManualResetEvent by passing a Boolean value to the constructor, true if the initial state is signaled and false otherwise.
ManualResetEvent can also be used with the static WaitAll and WaitAny methods.
练习
============
看懂下面的一段代码吧.
The following code example demonstrates how to use wait handles to signal the completion of various stages of a complicated number calculation. The calculation is of the form: result = first term + second term + third term, where each term requires a precalculation and a final calculation using a calculated base number.
1: using System;
2: using System.Threading;
3:
4: class CalculateTest
5: {
6: static void Main()
7: {
8: Calculate calc = new Calculate();
9: Console.WriteLine("Result = {0}.",
10: calc.Result(234).ToString());
11: Console.WriteLine("Result = {0}.",
12: calc.Result(55).ToString());
13: }
14: }
15:
16: class Calculate
17: {
18: double baseNumber, firstTerm, secondTerm, thirdTerm;
19: AutoResetEvent[] autoEvents;
20: ManualResetEvent manualEvent;
21:
22: // Generate random numbers to simulate the actual calculations.
23: Random randomGenerator;
24:
25: public Calculate()
26: {
27: autoEvents = new AutoResetEvent[]
28: {
29: new AutoResetEvent(false),
30: new AutoResetEvent(false),
31: new AutoResetEvent(false)
32: };
33:
34: manualEvent = new ManualResetEvent(false);
35: }
36:
37: void CalculateBase(object stateInfo)
38: {
39: baseNumber = randomGenerator.NextDouble();
40:
41: // Signal that baseNumber is ready.
42: manualEvent.Set();
43: }
44:
45: // The following CalculateX methods all perform the same
46: // series of steps as commented in CalculateFirstTerm.
47:
48: void CalculateFirstTerm(object stateInfo)
49: {
50: // Perform a precalculation.
51: double preCalc = randomGenerator.NextDouble();
52:
53: // Wait for baseNumber to be calculated.
54: manualEvent.WaitOne();
55:
56: // Calculate the first term from preCalc and baseNumber.
57: firstTerm = preCalc * baseNumber *
58: randomGenerator.NextDouble();
59:
60: // Signal that the calculation is finished.
61: autoEvents[0].Set();
62: }
63:
64: void CalculateSecondTerm(object stateInfo)
65: {
66: double preCalc = randomGenerator.NextDouble();
67: manualEvent.WaitOne();
68: secondTerm = preCalc * baseNumber *
69: randomGenerator.NextDouble();
70: autoEvents[1].Set();
71: }
72:
73: void CalculateThirdTerm(object stateInfo)
74: {
75: double preCalc = randomGenerator.NextDouble();
76: manualEvent.WaitOne();
77: thirdTerm = preCalc * baseNumber *
78: randomGenerator.NextDouble();
79: autoEvents[2].Set();
80: }
81:
82: public double Result(int seed)
83: {
84: randomGenerator = new Random(seed);
85:
86: // Simultaneously calculate the terms.
87: ThreadPool.QueueUserWorkItem(
88: new WaitCallback(CalculateBase));
89: ThreadPool.QueueUserWorkItem(
90: new WaitCallback(CalculateFirstTerm));
91: ThreadPool.QueueUserWorkItem(
92: new WaitCallback(CalculateSecondTerm));
93: ThreadPool.QueueUserWorkItem(
94: new WaitCallback(CalculateThirdTerm));
95:
96: // Wait for all of the terms to be calculated.
97: WaitHandle.WaitAll(autoEvents);
98:
99: // Reset the wait handle for the next calculation.
100: manualEvent.Reset();
101:
102: return firstTerm + secondTerm + thirdTerm;
103: }
104: }