views:

111

answers:

3

I have a device (digital indicator) that I am communicating with using the SerialPort class. The device documentation states that I need to have a 250 millisecond delay between writes. Is there a way to enforce this without putting extra delay into the system? I know this probably sounds like I'm worrying too much about something that's really small, but there are three of these indicators and it is reading them quite often, but not all the time. Basically, is there a good way to enforce that you don't send again in less than 250 milliseconds, but if it's been 5 seconds and I try to send, I don't want to delay an additional 250 milliseconds for no reason.

Thoughts?

+1  A: 

Suspending the thread should work for you:

System.Threading.Thread.Sleep(250);

However, this can be a little inaccurate since you can't guarantee the next time your thread is going to be scheduled. If you need precise timings, you'd better use spin waits.

Mehrdad Afshari
This doesn't answer the question. This would cause it to wait 250 milliseconds no matter what.
Max Schmeling
@Max: You can use `Stopwatch` to calculate the time already passed since you wrote last time to the port and adjust the delay appropriately.
Mehrdad Afshari
+2  A: 

You should have some sort of class for the purpose of writing to the serial port, perhaps a single point of writing (a WriteToPort function or something).

In that, you could save the current time every time you write, then use logic on the delay for that. SO:

DateTime lastWritten;
TimeSpan timeBetweenWrites = new Timespan(0,0,0,0,250);
void WriteToDevice(string data)
{
    TimeSpan sinceLastWrite=DateTime.Now-lastWritten;
    if(sinceLastWrite<timeBetweenWrites)
        Thread.Sleep(timeBetweenWrites-sinceLastWrite);
    SerialPort.Write(data);
    lastWritten=DateTime.Now;
}
Erich
This is what I was planning on doing. I was hoping there was some more elegant way of doing it, but I guess there probably isn't. thanks
Max Schmeling
Alternatively, if you are willing to make your writes not necessarily 'serial' and are willing to submit them Asynchronously, you can create a thread to do the submissions that will sleep 250ms between each send, and then just wait on a lock to send in order to send.I didn't write that one up, because it is a bit more complex, and most Serial Port usage requires that the data be dealt with in a syncronous way.
Erich
Yeah, unfortunately it needs to be done in a synchronous manner
Max Schmeling
Variation: Have it throw an exception instead of sleeping. That way, the information is passed out instead of just automatically blocking the caller for however long. Depends on the use case into the method.
jdmichal
Exceptions are to be used for 'exceptional' circumstances. They should not be used for program flow.
Erich
Yes. I would consider an attempt to `WriteToDevice` at a time when writing is not permitted to be an "exceptional circumstance". As I said, it depends on the use case into the method. If it is appropriate to block the calling thread until a write can be successfully made, then the sleeping implementation is fine. But there are also use cases where blocking the thread would not be OK, in which case it would be more desirable to exception out.
jdmichal
A: 

Fetch a timestamp before each transmission. Sleep for the 250-(now - then) milliseconds (clamped at zero, obviously). That seems to be what you're asking for.

If, instead, you're worried about things like OS scheduling issues making times that are not 250ms on average, or more than a tiny bit off from 250ms exactly, then you have a harder problem on our hand and you will need to read up on hard real time techniques (and perhaps purchase some extra hardware).

Andy Ross