It is the generic brand for multi-threading

In the prior post, I talked about getting the system thread safe.  I didn’t make the methods generic as that would have added in more complexity and I just wanted it to work.

Now as all good coders know, cutting and copying code is the work of vegans and hippies and should be stopped.  So how should we make it reusable rather than a suburb where everything is a slightly tweaked copy of one another.

So lets see how I’d call the Reset method.

I’ll need 3 things

  • The public method
  • The SerialPort DataRecieved event delegate
  • And the worker delegate

public string Reset()
{
	var returnVal = (string)executeComportCall(5, 5000, resetWorker, resetOrFirmwareDataReceived);
	return returnVal;
}

private void resetOrFirmwareDataReceived(object sender, SerialDataReceivedEventArgs e)
{
	var returnVal = comport.ReadLine();

	if (isInvalidResponse(returnVal))
		return;

	comportReturnObject = returnVal;
	comportSingleAccessWait.Set();
}

private void resetWorker()
{
	comport.Write(reset);
}

Pretty easy and straight forward.  Want to add in a new feature, all you need is 3 small functions with no fusing about threading.

But where did that threading code go?

private AutoResetEvent comportSingleAccessWait;
private readonly Mutex comportMutex = new Mutex();
private object comportReturnObject;

private delegate void WorkerDelegate();
private object executeComportCall(int maxRetryTimes, int millisecondsToRetry, WorkerDelegate workerDelegate, SerialDataReceivedEventHandler DataRecievedHandler)
{
	comportMutex.WaitOne();
	comportReturnObject = null;

	comport.DiscardInBuffer();
	comport.DataReceived += DataRecievedHandler;
	comportSingleAccessWait = new AutoResetEvent(false);

	for (var i = 0; i < maxRetryTimes; i++)
	{
		if (comportReturnObject != null)
			break;

		workerDelegate();

		comportSingleAccessWait.WaitOne(millisecondsToRetry);
	}

	comport.DataReceived -= DataRecievedHandler;
	comportMutex.ReleaseMutex();
	return comportReturnObject;
}

private static bool isInvalidResponse(string value)
{
	return string.IsNullOrEmpty(value) ||
		value == returnLine ||
		value == nack;
}

So why do I have a worker delegate when it could be a very simple thing?  For me, I have my OpenRelay method (which I haven’t written yet) that has to add in yet another Auto Reset Event since I have to watch how big of a command I send in.  If I get past the max amount, I have to stop, send in what I have, wait, and then send in the rest when the current is done pouring.

Yes, I do think I’ll have the only thread-safe bartender system.

No comments posted yet.

Post a Comment

Please add 1 and 2 and type the answer here: