AutoResetEvent:
AutoResetEvent 构造函数可以传入一个bool类型的参数,false表示将AutoResetEvent对象的初始状态设置为非终止。如果为true标识终止状态,那么WaitOne方法就不会再阻塞线程了。但是因为该类会自动的将终止状态修改为非终止,所以,之后再调用WaitOne方法就会被阻塞。
WaitOne 方法如果AutoResetEvent对象状态非终止,则阻塞调用该方法的线程。可以指定时间,若没有获取到信号,返回false
set 方法释放被阻塞的线程。但是一次只可以释放一个被阻塞的线程。
class ThreadSafe
{
static AutoResetEvent autoEvent;
static void Main()
{
//使AutoResetEvent处于非终止状态
autoEvent = new AutoResetEvent(false);
Console.WriteLine("主线程运行...");
Thread t = new Thread(DoWork);
t.Start();
Console.WriteLine("主线程sleep 1秒...");
Thread.Sleep(1000);
Console.WriteLine("主线程释放信号...");
autoEvent.Set();
}
static void DoWork()
{
Console.WriteLine(" t线程运行DoWork方法,阻塞自己等待main线程信号...");
autoEvent.WaitOne();
Console.WriteLine(" t线程DoWork方法获取到main线程信号,继续执行...");
}
}
输出
主线程运行...
主线程sleep 1秒...
t线程运行DoWork方法,阻塞自己等待main线程信号...
主线程释放信号...
t线程DoWork方法获取到main线程信号,继续执行...
ManualResetEvent
ManualResetEvent和AutoResetEvent用法类似。
AutoResetEvent在调用了Set方法后,会自动的将信号由释放(终止)改为阻塞(非终止),一次只有一个线程会得到释放信号。而ManualResetEvent在调用Set方法后不会自动的将信号由释放(终止)改为阻塞(非终止),而是一直保持释放信号,使得一次有多个被阻塞线程运行,只能手动的调用Reset方法,将信号由释放(终止)改为阻塞(非终止),之后的再调用Wait.One方法的线程才会被再次阻塞。
public class ThreadSafe
{
//创建一个处于非终止状态的ManualResetEvent
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main()
{
for(int i = 0; i <= 2; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("n新线程的方法已经启动,且被阻塞,调用Set释放阻塞线程");
mre.Set();
Thread.Sleep(500);
Console.WriteLine("n当ManualResetEvent处于终止状态时,调用由Wait.One方法的多线程,不会被阻塞。");
for(int i = 3; i <= 4; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("n调用Reset方法,ManualResetEvent处于非阻塞状态,此时调用Wait.One方法的线程再次被阻塞");
mre.Reset();
Thread t5 = new Thread(ThreadProc);
t5.Name = "Thread_5";
t5.Start();
Thread.Sleep(500);
Console.WriteLine("n调用Set方法,释放阻塞线程");
mre.Set();
}
private static void ThreadProc()
{
string name = Thread.CurrentThread.Name;
Console.WriteLine(name + " 运行并调用WaitOne()");
mre.WaitOne();
Console.WriteLine(name + " 结束");
}
}
//Thread_2 运行并调用WaitOne()
//Thread_1 运行并调用WaitOne()
//Thread_0 运行并调用WaitOne()
//新线程的方法已经启动,且被阻塞,调用Set释放阻塞线程
//Thread_2 结束
//Thread_1 结束
//Thread_0 结束
//当ManualResetEvent处于终止状态时,调用由Wait.One方法的多线程,不会被阻塞。
//Thread_3 运行并调用WaitOne()
//Thread_4 运行并调用WaitOne()
//Thread_4 结束
//Thread_3 结束
///调用Reset方法,ManualResetEvent处于非阻塞状态,此时调用Wait.One方法的线程再次被阻塞
//Thread_5 运行并调用WaitOne()
//调用Set方法,释放阻塞线程
//Thread_5 结束










