Вот очень простой пример; вызов Wait
снимает блокировку (позволяя Worker
получить ее) и добавляет поток Main
в очередь ожидания объекта блокировки. Worker
затем получает блокировку и вызывает Pulse
: это перемещает поток Main
в очередь готовности объекта блокировки. Когда Worker
снимает блокировку, Main
может возобновить работу.
Обратите внимание, что lock(obj) {...}
это просто конфетка компилятора для Monitor.Enter
/ Monitor.Exit
в блоке try / finally.
[править: я изменил семпл, чтобы переместить lock(sync)
ранее, чтобы избежать (маловероятного) риска пропущенного импульса]
static void Main()
{
object sync = new object();
lock (sync)
{
ThreadPool.QueueUserWorkItem(Worker, sync);
Console.WriteLine("Main sleeping");
// wait for the worker to tell us it is ready
Monitor.Wait(sync);
Console.WriteLine("Main woke up!");
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
static void Worker(object sync)
{
Console.WriteLine("Worker started; about to sleep");
Thread.Sleep(5000);
Console.WriteLine("Worker about pulse");
lock (sync)
{ // notify Main that we did something interesting
Monitor.Pulse(sync);
Console.WriteLine("Worker pulsed; about to release lock");
}
Console.WriteLine("Worker all done");
}