c# WaitHandle的WaitOne(int, bool)方法
WaitHandle类用于线程的同步。WaitOne方法用于阻止当前线程,直到当前WaitHandle接收到信号。
WaitOne(int, bool)方法是其中的一个重载。
第一个参数很好理解,表示当前线程等待信号的超时时间,单位是ms。
第二个参数表示等待之前是否退出上下文的同步域,true表示退出,false表示不退出。
用微软自身的例子来解释,下面是例子:
using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;
[Synchronization(true)]
public class SyncingClass : ContextBoundObject
{
private EventWaitHandle waitHandle;
public SyncingClass()
{
waitHandle =
new EventWaitHandle(false, EventResetMode.ManualReset);
}
public void Signal()
{
Console.WriteLine("Thread[{0:d4}]: Signalling...", Thread.CurrentThread.GetHashCode());
waitHandle.Set();
}
public void DoWait(bool leaveContext)
{
bool signalled;
waitHandle.Reset();
Console.WriteLine("Thread[{0:d4}]: Waiting...", Thread.CurrentThread.GetHashCode());
signalled = waitHandle.WaitOne(10000, leaveContext);
if (signalled)
{
Console.WriteLine("Thread[{0:d4}]: Wait released!!!", Thread.CurrentThread.GetHashCode());
}
else
{
Console.WriteLine("Thread[{0:d4}]: Wait timeout!!!", Thread.CurrentThread.GetHashCode());
}
}
}
public class TestSyncDomainWait
{
public static void Main()
{
SyncingClass syncClass = new SyncingClass();
Thread runWaiter;
Console.WriteLine("\nWait and signal INSIDE synchronization domain:\n");
runWaiter = new Thread(RunWaitKeepContext);
runWaiter.Start(syncClass);
Thread.Sleep(1000);
Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
// This call to Signal will block until the timeout in DoWait expires.
syncClass.Signal();
runWaiter.Join();
Console.WriteLine("\nWait and signal OUTSIDE synchronization domain:\n");
runWaiter = new Thread(RunWaitLeaveContext);
runWaiter.Start(syncClass);
Thread.Sleep(1000);
Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
// This call to Signal is unblocked and will set the wait handle to
// release the waiting thread.
syncClass.Signal();
runWaiter.Join();
}
public static void RunWaitKeepContext(object parm)
{
((SyncingClass)parm).DoWait(false);
}
public static void RunWaitLeaveContext(object parm)
{
((SyncingClass)parm).DoWait(true);
}
}
// The output for the example program will be similar to the following:
//
// Wait and signal INSIDE synchronization domain:
//
// Thread[0004]: Waiting...
// Thread[0001]: Signal...
// Thread[0004]: Wait timeout!!!
// Thread[0001]: Signalling...
//
// Wait and signal OUTSIDE synchronization domain:
//
// Thread[0006]: Waiting...
// Thread[0001]: Signal...
// Thread[0001]: Signalling...
// Thread[0006]: Wait released!!!
代码第5行,[Synchronization(true)]表示类SyncingClass(继承自ContextBoundObject)是一个同步域上下文类。它表示如果我们创建了一个这个SyncingClass类的一个实例,那么每个时刻只能由一个线程访问这个类实例,否则就被阻塞,一直等到其他线程访问的释放。
WaitHandle.WaitOne的第二个参数如果是false,意味着调用这个WaitOne的线程会保持上下文不变,也就意味着不会释放SyncingClass实例的占用。代码运行到54行也就会被阻塞住。
而如果WaitOne的第二个参数时true,那么好比是SyncingClass开了个后门,可以在WaitOne之前释放对自己的占用,便于我们访问这个实例的其他方法不被阻塞,因此这个时候64行顺利发送信号。