2

I am designing an industrial hardware control program in C#, which will run for periods of 72 hours at a time talking over serial ports.

In psuedo-code, what I am trying to do looks like this:-

while(true) {
    TalkToSerialPort1();
    WaitForXHours(3);
    TalkToSerialPort2();
    WaitForXHours(1);
    // etc
}

I have this code in a separate thread from my main console or GUI program and has to be run procedureally

It seems like Thread.Sleep() for long periods of time seems to be ruining my day! I am looking for a reliable way of sleeping for extended periods of time.

Any information would be helpful.

Dhanuka
  • 2,826
  • 5
  • 27
  • 38
Chris
  • 23
  • 3
  • This link might assist you [http://stackoverflow.com/questions/5424667/alternatives-to-thread-sleep][1] [1]: http://stackoverflow.com/questions/5424667/alternatives-to-thread-sleep – liorlis Jun 28 '15 at 11:24
  • I don't think you should be using a Sleep() method. Instead synchronize the thread using a WaitHandle. – jdweng Jun 28 '15 at 11:31
  • At the end of the 72 hours, does the program finish or do you want to repeat? What will happen if the program crashes? Will it need to restart at the point it failed? There are many ways this can be structured. – Dennis Jun 28 '15 at 11:33
  • Why doesn't this work for you? It should. Of course you'll have timing skew because TalkToSerialPort1 takes some time. – usr Jun 28 '15 at 11:45

4 Answers4

2

You should use Quartz .NET it is reliable and very accurate scheduler. Read more here: https://www.quartz-scheduler.net/

Major
  • 5,948
  • 2
  • 45
  • 60
1

A Stopwatch is a better way to solve this**. For example:

    Stopwatch spw = new Stopwatch();            

    int stepNo = 0;
    while (!haltWork)
    {
        Thread.Sleep(100);
        switch (stepNo)
        {
            case 0:
                TalkToSerialPort1();
                spw.Restart();
                stepNo += 1;
                break;
            case 1:
                if (spw.Elapsed.Hours >= 3)
                {
                    TalkToSerialPort2();
                    spw.Restart();
                    stepNo += 1;
                }
                break;
            case 2:
                if (spw.Elapsed.Hours >= 1)
                {
                    TalkToSerialPort3();
                    spw.Restart();
                    stepNo += 1;
                }
                break;
            // etc...

        }
    }

Here I've added a condition haltWork - your main program will need some way to signal this thread to exit in a timely fashion if necessary. This runs the thread in a polling loop that will allow it to break and exit, supports user cancellation, and, because of the stopwatch, will provide you the precise time elapsed for the current step in the case of user cancellation that you can use for process diagnostics, restart procedures, etc.

The procedural process is broken up into steps using a switch statement. This lets you perform long running procedural processes with waiting or polling steps in a clean and logical manner while also remaining responsive, able to provide active feedback (consider raising events periodically to alert the main thread of your current step, time elapsed, etc, for process logging purposes).

Note also that this example resets the stopwatch at each step - how you do this depends on your requirements; whether you need to control the interval between steps or whether it is more important to keep regular pace with respect to an arbitrary reference. If the latter, naturally just start the stopwatch once and make the rest of your intervals absolute rather than relative.


** I am proceeding from the assumption that doing this inside your C# application has been thought out carefully and that this is the best place to take responsibility for this task.

The windows task scheduler is one alternative place to handle repetitive "headless" tasks that need to be run at long intervals.

Another alternative, especially relevant to industrial control, is to use dedicated hardware to do this - a small PLC, etc.

J...
  • 30,968
  • 6
  • 66
  • 143
1

Alternative approach would be to use a Timer

for example calling method on every x minutes

Note : that in this case - You must ensure that previous operation has finished, before starting a new one.

Community
  • 1
  • 1
Marty
  • 3,485
  • 8
  • 38
  • 69
0

well - if You want to stick to the "while (true)" pattern, what You can do is smth like this:

while (true){

if (DateTime.Now - LastExecutionDate > 72h)
{
   doYourStuff();
   Update_LastExecutionDate;
}
else{
  continue; //or sleep for 5 minutes
}
Marty
  • 3,485
  • 8
  • 38
  • 69