namespace ConsoleTest
{
//下面代码说明在进程等待后台线程执行完时,如何使用等待句柄阻止进程终止。
class Program
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("Main starting.");
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod), autoEvent);
//if (autoEvent.WaitOne(1000, false))
// Console.WriteLine("Work method signaled.");
//else
// Console.WriteLine("Time out waiting for work "+"method to signal.");
//Wait for work method to signal.
autoEvent.WaitOne();
Console.WriteLine("Main ending.");
}
static void WorkMethod(object stateInfo)
{
Console.WriteLine("Work starting.");
Thread.Sleep(new Random().Next(100, 2000));
Console.WriteLine("Work ending.");
((AutoResetEvent)stateInfo).Set();
}
}
}
执行结果:
Main starting.
Work starting.
Work ending.
Main ending.
WaitOne:在一个线程MainThread中开启一个新的线程NewThread,在完成初始化并启动NewThread的操作后,调用WaitOne,则MainThread堵塞,直到在NewThread中调用Set,MainThread才继续执行。
AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。
线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set 发出资源可用的信号。
调用 Set 向 AutoResetEvent 发信号以释放等待线程。AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待,则状态将无限期地保持为终止状态。
可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为终止状态,则为 true;否则为 false。
通俗的来讲只有等myResetEven.Set()成功运行后,myResetEven.WaitOne()才能够获得运行机会;Set是发信号,WaitOne是等待信号,只有发了信号,等待的才会执行。如果不发的话,WaitOne后面的程序就永远不会执行。
下面我们来举一个例子:我去书店买书,当我选中一本书后我会去收费处付钱,
付好钱后再去仓库取书。这个顺序不能颠倒,我作为主线程,收费处和仓库做两个辅助线程,代码如下:
namespace AutoResetEventDemo
{
class Program
{
const int num = 550;
static AutoResetEvent myResetEvent = new AutoResetEvent(false);
static AutoResetEvent changeEvent = new AutoResetEvent(false);
static int number;//这是关键资源
static void PayMoneyProc()
{
while (true)
{
myResetEvent.WaitOne();
Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
}
}
static void GetBookProc()
{
while (true)
{
changeEvent.WaitOne();
Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
Console.WriteLine("------------------------------");
Thread.Sleep(0);
}
}
static void Main()
{
Thread payMoneyThread = new Thread(new ThreadStart(PayMoneyProc));
payMoneyThread.Name = "付钱线程";
Thread getBookThread = new Thread(new ThreadStart(GetBookProc));
getBookThread.Name = "取书线程";
payMoneyThread.Start();
getBookThread.Start();
for (int i = 1; i < num; i++)
{
Console.WriteLine("买书线程:数量{0}",i);
number = i;
myResetEvent.Set();
changeEvent.Set();
Thread.Sleep(0);
}
payMoneyThread.Abort();//调用此方法通常会终止线程
getBookThread.Abort();
}
}
}