Excellent examples. Thank you very much. I have managed to get a simple
shared counter working. One thread tries to increment the counter, the other
tries to decrement the counter. All while updating the GUI through
delegates.
One thing I remain unclear on is the ManualResetEvent variables. I've been
able (I think) to implement these successfully, but I really want to
understand their purpose, when to use them, when not to use them. Why could
I not just use a reference to a boolean variable to stop the thread. I
assume that is because it would not be thread safe. If anyone can explain
this to me that would be most excellent.
Thanks.
// Counter class
public class Counter
{
private readonly object countLock = new object();
private int count = 0;
private ManualResetEvent incStop;
private ManualResetEvent incStopped;
private ManualResetEvent decStop;
private ManualResetEvent decStopped;
private MainForm frm;
public Counter(ManualResetEvent incrementStop, ManualResetEvent
incrementStopped, ManualResetEvent decrementStop, ManualResetEvent
decrementStopped, MainForm form)
{
incStop = incrementStop;
incStopped = incrementStopped;
decStop = decrementStop;
decStopped = decrementStopped;
frm = form;
}
public void Increment(int val, int sleep)
{
while(true)
{
lock(countLock)
{
int tmp = count;
frm.Invoke(frm.AddStringIncrementDelegate, new object[] {"Reading
Value: " + Convert.ToString(tmp)});
frm.Invoke(frm.AddStringDecrementDelegate, new object[] {""});
tmp = tmp + val;
frm.Invoke(frm.AddStringIncrementDelegate, new object[]
{"Incremented by: " + Convert.ToString(val)});
frm.Invoke(frm.AddStringDecrementDelegate, new object[] {""});
count = tmp;
frm.Invoke(frm.AddStringIncrementDelegate, new object[] {"Writing
Value: " + Convert.ToString(tmp)});
frm.Invoke(frm.AddStringDecrementDelegate, new object[] {""});
frm.Invoke(frm.SetCurrentCountDelegate, new object[]
{Convert.ToString(count)});
Thread.Sleep(sleep);
if(incStop.WaitOne(0, true))
{
incStopped.Set();
return;
}
}
}
frm.Invoke(frm.IncrementThreadFinishedDelegate, null);
}
}
// Called in the form when the stop thread button is pressed.
private void StopIncrement()
{
if(incrementThread != null && incrementThread.IsAlive) // thread is active
{
// set event "Stop"
incrementStopEvent.Set();
// wait when thread will stop or finish
while(incrementThread.IsAlive)
{
if(WaitHandle.WaitAll((new ManualResetEvent[]
{incrementStoppedEvent}), 100, true))
{
break;
}
Application.DoEvents();
}
}
IncrementThreadFinished(); // set initial state of buttons
}
// counter class initialization
incrementStopEvent = new ManualResetEvent(false);
incrementStoppedEvent = new ManualResetEvent(false);
decrementStopEvent = new ManualResetEvent(false);
decrementStoppedEvent = new ManualResetEvent(false);
counter = new Counter(incrementStopEvent, incrementStoppedEvent,
decrementStopEvent, decrementStoppedEvent, this);