WaitHandle
基本概念是什么?
它的用途是什么?
何时使用?
WaitHandle
中的WaitAll和WaitAny方法的用途是什么?WaitHandle
基本概念是什么?
它的用途是什么?
何时使用?
WaitHandle
中的WaitAll和WaitAny方法的用途是什么?WaitHandle
是您“使用”来控制线程执行的“机制”。它不是关于句柄在线程内不可访问;而是在线程内使用它们。something
发生时吹哨子;过程是每个女孩都吹哨子,女士就会知道是谁吹了哨子。WaitHandle.WaitAny(events);
3.在线程中完成操作后,.Set()
,这将告诉WaitHandle:“我完成了!”class Test
{
static void Main()
{
//STEP 1: Create a wait handle
ManualResetEvent[] events = new ManualResetEvent[10];//Create a wait handle
for (int i=0; i < events.Length; i++)
{
events[i] = new ManualResetEvent(false);
Runner r = new Runner(events[i], i);
new Thread(new ThreadStart(r.Run)).Start();
}
//STEP 2: Register for the events to wait for
int index = WaitHandle.WaitAny(events); //wait here for any event and print following line.
Console.WriteLine ("***** The winner is {0} *****",
index);
WaitHandle.WaitAll(events); //Wait for all of the threads to finish, that is, to call their cooresponding `.Set()` method.
Console.WriteLine ("All finished!");
}
}
class Runner
{
static readonly object rngLock = new object();
static Random rng = new Random();
ManualResetEvent ev;
int id;
internal Runner (ManualResetEvent ev, int id)
{
this.ev = ev;//Wait handle associated to each object, thread in this case.
this.id = id;
}
internal void Run()
{
//STEP 3: Do some work
for (int i=0; i < 10; i++)
{
int sleepTime;
// Not sure about the thread safety of Random...
lock (rngLock)
{
sleepTime = rng.Next(2000);
}
Thread.Sleep(sleepTime);
Console.WriteLine ("Runner {0} at stage {1}",
id, i);
}
//STEP 4: Im done!
ev.Set();
}
}
WaitHandle
是两个常用事件句柄类 AutoResetEvent
和 ManualResetEvent
的抽象基类。
这两个类允许一个线程“通知”一个或多个其他线程。它们用于在线程之间同步(或串行化活动)。可以使用 Set
和 WaitOne
(或 WaitAll
)方法来实现。例如:
线程1:
// do setup work
myWaitHandle.Set();
线程 2:
// do setup work
myWaitHandle.WaitOne();
// this code will not continue until after the call to `Set`
// in thread 1 completes.
这只是一个非常基础的示例,网络上有许多类似的示例。基本思想是使用 WaitOne
等待来自另一个线程的信号,指示发生了某些事情。对于异步调用委托时返回的 AsyncWaitHandle
(它会异步返回),WaitOne
允许您使当前线程等待直到异步操作完成。
当 AutoResetEvent
或 ManualResetEvent
没有设置时,调用 WaitOne
将阻塞调用线程,直到调用 Set
。这两个类唯一的区别在于,AutoResetEvent
在成功调用 WaitOne
完成后“取消”事件,使后续调用再次阻塞,直到调用 Set
。必须通过调用 Reset
显式地取消 ManualResetEvent
。
WaitAll
和 WaitAny
是位于 WaitHandle
类上的静态方法,允许您指定要等待的 WaitHandles
数组。 WaitAll
将阻塞,直到所有提供的句柄都已设置,而 WaitAny
仅在其中之一被设置时阻塞。
这是一个抽象类,不能直接使用。具体的派生类有ManualResetEvent、AutoResetEvent、Mutex和Semaphore。它们是实现线程同步的重要工具箱类。它们继承了WaitOne、WaitAll和WaitAny方法,您可以使用它们来检测一个或多个线程发出的等待条件信号。
Manual/AutoResetEvent的典型用法场景是告诉线程退出或让线程发出已经进入重要序列点的信号。Semaphore帮助您限制执行操作的线程数。或者实现不应与特定线程相关联的线程同步。Mutex则用于将代码段的所有权分配给一个线程,lock语句在那里也经常适用。
关于这方面的书籍已经写了很多。Joe Duffy的Concurrent Programming in Windows是最新、最好的一本。如果您考虑编写多线程代码,强烈推荐阅读。
WaitOne
,WaitAll
和WaitAny
方法。通过选择这些类之一,可以选择可用的语义选项:Mutex
,Semaphore
,ManualResetEvent
,AutoResetEvent
,这些都有很好的文档记录。
ev.Set()
最好放在finally
块中。 - Hakan Fıstık