Monitor.Pulse question

D

DeveloperX

Hi, Below is a hacked up version of an example I found on MSDN. My only
change was to add a third thread and some Sleeps. That's where my
question(s) comes in.
In the original it seems to work because Thread1 waits on Thread2 and
vice versa, although I can't quite see how.
Disabling Thread3 and leaving the sleep in works fine, processing is
nicely throttled. Activating Thread3 and we enter a world of pain. I
don't understand what the first Pulse is doing in Thread2, I think I
understand the second one, and the purpose of the Wait, although how
it's reached inside the Lock statement confuses me.

Here's the code,it should work pasted verbatim into a console app. If
someone has a simple explanation of what Pulse is supposed to do, and
how the various competing lock statements interact, or even how to make
the code below function (ie Thread1 pumps out stuff, Thread2 and 3
consume it when they can), then I'll be a happy bunny.

Thanks.

using System;
using System.Threading;
using System.Collections;

namespace MonitorCS1
{
class MonitorSample
{
const int MAX_LOOP_TIME = 1000;
Queue m_smplQueue;
Random r = new Random(1);

public MonitorSample()
{
m_smplQueue = new Queue();
}
public void FirstThread()
{
int counter = 0;
lock(m_smplQueue)
{
while(counter < MAX_LOOP_TIME)
{
//Wait, if the queue is busy.
Monitor.Wait(m_smplQueue);
//Push one element.
m_smplQueue.Enqueue(counter);
//Release the waiting thread.
Monitor.Pulse(m_smplQueue);

counter++;
}
}
}
public void SecondThread()
{
lock(m_smplQueue)
{
//Release the waiting thread.
Monitor.Pulse(m_smplQueue);
//Wait in the loop, while the queue is busy.
//Exit on the time-out when the first thread stops.
while(Monitor.Wait(m_smplQueue,1000))
{
//Pop the first element.
int counter = (int)m_smplQueue.Dequeue();
//Print the first element.
Console.WriteLine("Second " + counter.ToString());
//Release the waiting thread.
Monitor.Pulse(m_smplQueue);
Thread.Sleep(r.Next(20));
}
}

}
public void ThirdThread()
{
lock(m_smplQueue)
{
//Release the waiting thread.
Monitor.Pulse(m_smplQueue);
//Wait in the loop, while the queue is busy.
//Exit on the time-out when the first thread stops.
while(Monitor.Wait(m_smplQueue,1000))
{
//Pop the first element.
int counter = (int)m_smplQueue.Dequeue();
//Print the first element.
Console.WriteLine("Third " + counter.ToString());
//Release the waiting thread.
Monitor.Pulse(m_smplQueue);
Thread.Sleep(r.Next(20));
}
}
}
//Return the number of queue elements.
public int GetQueueCount()
{
return m_smplQueue.Count;
}

static void Main(string[] args)
{
//Create the MonitorSample object.
MonitorSample test = new MonitorSample();
//Create the first thread.
Thread tFirst = new Thread(new ThreadStart(test.FirstThread));
//Create the second thread.
Thread tSecond = new Thread(new ThreadStart(test.SecondThread));

Thread tThird = new Thread(new ThreadStart(test.ThirdThread));
//Start threads.
tFirst.Start();
tSecond.Start();
tThird.Start();
//wait to the end of the two threads
tFirst.Join();
tSecond.Join();
tThird.Join();
//Print the number of queue elements.
Console.WriteLine("Queue Count = " +
test.GetQueueCount().ToString());
}
}
}
 
D

DeveloperX

Solved it... Sort of,Replacing the While in Thread2 and 3 with:

while(Monitor.Wait(m_smplQueue))
{
if(m_smplQueue.Count>0)
{
//Pop the first element.
int counter = (int)m_smplQueue.Dequeue();
//Print the first element.
Console.WriteLine("Third " + counter.ToString());
//Release the waiting thread.
}
Monitor.Pulse(m_smplQueue);
Thread.Sleep(r.Next(50));
}

Solves the problem, I still don't know what the first Pulse is for
though in Threads 2 and 3.
Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top