?
Solved

Help with my Timer Function

Posted on 2006-06-01
10
Medium Priority
?
317 Views
Last Modified: 2012-05-07
Hello everyone,

In an old question "krbatge" helped me with a timer function. Here is that thread:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21666588.html

My program is creating clips every ten minutes. So basically I want the clips to all start on the TENS. Meaning 10:00:00, 10:10:00, 10:20:00, 10:30:00, etc.

So if the program started at 12:35:29 the first timer would figure out the time until the next TENS (12:40:00) and make the time for that...which is this example is 00:04:31. Then the secondary timer that would keep everything running on the TENS would be in the timer function.

Everything seems to work well....except after running for a couple of days it starts to get out of wack. It starts slowly like so. 12:00:01, 12:00:02, 12:00:03,  until eventually my clip files no longer start on the TENS.

So I need a way of testing to make sure that everything is still running on the TENS.

The first timer that checks the current time and makes a timer to get to the first TENS:
-----------------------------------------------------
time_t ltime;
struct tm now;
time(&ltime);
now = *localtime(&ltime);
int nMinsTillTen = (10 - (now.tm_min % 10));
int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);


Here is the timer in the OnTimer function to run every ten minutes:
-------------------------------------------------------
OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);


Can someone please help me figure a way out to keep it sync'd and always running on the TENS. I was thinking maybe a way to check the time and if its not on the TENS restart the first timer to put us back in place. I tried but couldn't get it to work. Any tips, pushes in the right direction, or code is greatly appreciated.

- James
0
Comment
Question by:VirtueTech
  • 4
  • 4
  • 2
10 Comments
 
LVL 8

Expert Comment

by:krbatge
ID: 16813013
Can you post the full code you have in OnTimer?
0
 

Author Comment

by:VirtueTech
ID: 16813171
My OnTimer looks like this:
else if (nIDEvent == 15) // JLM
{      
// ************* This timer runs every 10 Minutes to create clips *********************************
// After 10 minutes time
// Stop Capture
      if (UseOnStartTimerOne == 0) {
            UseOnStartTimerOne = 1;
            KillTimer(OnStartTimerOne);
      }
      OnStop();
      OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);
      OnStart();
}


=======================================================
Now my "OnStop" functon:
=======================================================
void CHKVisionDlg::OnStop()
{
      CString msg;

      // The following creates a temp variable so its not lost for the thread
      TEMPtimeFileDBStart = timeFileDBStart;
      ULONG endCode = END_CODE;
      for(int i = 0; i < GetTotalDSPs(); i++){            
            _write(gFileHandle[i], &endCode, sizeof(ULONG));
            _close(gFileHandle[i]);
      }
      THREADlpszDateDirectory = lpszDateDirectory;
      THREADlpszTimeFile = lpszTimeFile;
      timeFileDBEnd = CTime::GetCurrentTime();

      // ************************ Removing for the OnStop Thread *************
      DWORD dw;
      if (m_hOnStopThread == NULL)
      {
            m_hOnStopThread = CreateThread(NULL,0, LPTHREAD_START_ROUTINE (OnStopThread),this,0,&dw);
            
            if(!(m_hOnStopThread))
            {
                  return;
            }
      }
      else
      {
            //debug only - MessageBox("OnStopThread - Previous thread never got set to NULL");
      }
      // **************** END - Removing for Onstop Thread ********************

      capimageX = 0;
}


========================================================
Now my "OnStart" function
========================================================
void CHKVisionDlg::OnStart()
{
      // make sure we have the directory for today's clips
      CString formatStr= _T("%Y%m%d");
      lpszDateDirectory = CTime:: GetCurrentTime().Format(formatStr);
            
      // Format the current time for string
      formatStr= _T("%H%M%S");
      lpszTimeFile = CTime::GetCurrentTime().Format(formatStr);

            
      if (bWorking = finder.FindFile(DriveLetter + ":\\clips\\" + lpszDateDirectory  ))
      {
            bWorking = finder.FindNextFile();
            if (!finder.IsDirectory())
                  if (!CreateDirectory(DriveLetter + ":\\clips\\" + lpszDateDirectory ,NULL))
                        MessageBox("Unable to Create Clips Directory");
      }
      else
            if (!CreateDirectory(DriveLetter + ":\\clips\\" + lpszDateDirectory ,NULL))
                        MessageBox("Unable to Create Day Directory");
            
            
      for(int i = 0; i < GetTotalDSPs(); i++)
      {
            streamX[i] = 0;
            sprintf(fileName, DriveLetter + ":\\clips\\" + lpszDateDirectory + "\\" + strDVRID + "_%d_%s_%s.mp4", i, lpszDateDirectory, lpszTimeFile);
            gFileHandle[i] = _open(fileName, _O_CREAT | _O_BINARY | _O_WRONLY| _O_TRUNC, _S_IREAD | _S_IWRITE);
            if (TurnPreviewOn == 1) {
                  sprintf(filePreviewName, DriveLetter + ":\\clips\\" + lpszDateDirectory + "\\pre_" + strDVRID + "_%d_%s_%s.mp4", i, lpszDateDirectory, lpszTimeFile);
                  gFilePreviewHandle[i] = _open(filePreviewName, _O_CREAT | _O_BINARY | _O_WRONLY| _O_TRUNC, _S_IREAD | _S_IWRITE);
            }            
            if(gFileHandle[i] == -1){
                  MessageBox("ERROR 1001: Cant open main channel clip. Please contact administrator with the error code.");
                  TRACE("channel %d file open error\n,i");
                  return;
            }
                  
            gChannelFrames[i] = 0;
            gChannelTotalLength[i] = 0;
            gChannelFramesLost[i] = 0;
            gChannelOverflow[i] = 0;
            gCurrentFileLen[i] = 0;
            ULONG length = 10000;
            gChannelTotalLength[i] += length;
            gCurrentFileLen[i] += length;
            _write(gFileHandle[i], FileHeader[i], FileHeaderLen);
            if (TurnPreviewOn == 1)
                  _write(gFilePreviewHandle[i], FilePreviewHeader[i], FilePreviewHeaderLen); // JLM
            gCaptureStartedNum++;

            CaptureIFrame(ChannelHandle[i]);
      }

      timeFileDBStart = CTime::GetCurrentTime();
      if(gCaptureStartedNum){
            m_ebRecordStatus.SetBkColor(RGB(255,255,255));
            m_ebRecordStatus.SetTextColor(RGB(0,160,0));
            m_ebRecordStatus.SetWindowText("Enabled");
      }

      // ******************* Setup Initial Timers ***************      
      if (TurnPreviewOn == 1) {
            previewTimer = SetTimer(16,30000,NULL); // Timer to create Preview Clip
            previewOff = FALSE;
      }
            
      // Setup 10 Minute Timer to keep the clips on the TENS: ex: 10:00:00, 10:10:00, 10:20:00
      if (UseOnStartTimerOne == 0) {
            time_t ltime;
            struct tm now;
            time(&ltime);
            now = *localtime(&ltime);
            int nMinsTillTen = (10 - (now.tm_min % 10));
            int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
            OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);
      }
            
}



----------------------------------------------------------------------
0
 
LVL 8

Expert Comment

by:krbatge
ID: 16813323
I'd say the timer is getting a bit out of sync because you restart it each time the OnTimer function is called. Try this instead -

My OnTimer looks like this:
else if (nIDEvent == 15) // JLM
{    
// ************* This timer runs every 10 Minutes to create clips *********************************
// After 10 minutes time
// Stop Capture
     if (UseOnStartTimerOne == 0) {
          UseOnStartTimerOne = 1;
          KillTimer(OnStartTimerOne);
          OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);  // Timer only needs to be started once
     }
     OnStop();
     // if you start the timer here each time you will introduce a small incremental delay because of the time it takes to process OnStop()
     OnStart();
}
 
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Expert Comment

by:krbatge
ID: 16813395
Additionally, if you wanted to be extra sure you could reset the timer say every 100 times or something...

e.g.

void CHKVisionDlg::ResetTensStartTimer()
{
          time_t ltime;
          struct tm now;
          time(&ltime);
          now = *localtime(&ltime);
          int nMinsTillTen = (10 - (now.tm_min % 10));
          int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
          OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);
}

void CHKVisionDlg::OnStart()
{
     .
     .
     .

    if (UseOnStartTimerOne == 0) {
          ResetTensStartTimer();
     }
}

void CHKVisionDlg::OnTimer(...)
{
    .
    .
    .
    else if (nIDEvent == 15) // JLM
    {    
         if (UseOnStartTimerOne == 0) {
              UseOnStartTimerOne = 1;
              KillTimer(OnStartTimerOne);
              OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);  // Second timer only needs to be started once
         }
         if (nTimerCount == 100)
         {
              // reset the timer to start again on the next 10 minute time in case we have got out of sync
              UseOnStartTimerOne = 0;
              KillTimer(OnStartTimerTwo);
              ResetTensStartTimer();
              nTimerCount = 0;
         }
         OnStop();
         OnStart();
         nTimerCount ++;  // global or member variable initially set to 0
    }
}



0
 
LVL 22

Expert Comment

by:grg99
ID: 16815456
If you want it to start EXACTLY on the dot, I'd set the timer for the destination time minus 10 seconds.

Then when the timer fires do:     while( TimeNow() < WantedTime ) Sleep( 1 ) ; // milisecond sleep!!

Also note that Windows is not a real-time system-- your program might be delayed indefinitely and unpredictably if some higher-priority task is running, or if VM fills up, or .....



0
 

Author Comment

by:VirtueTech
ID: 16816999
Thanks krbatge. I have implemented it....we'll see how it goes.

grg99:  In this scenario how do I no my "WantedTime". Because it keeps chaning. My wanted times would be 10:00:00, 10:10:00, 10:20:00, 10:30:00, 10:40:00, 10:50:00, 11:00:00

How would I make my "WantedTime" array/variable change so that it was looking for the right time on the TENS.

Example: If it is 11:50:00 how does my program now that the "WantedTime" should be equal to 12:00:00 ??
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 400 total points
ID: 16817570
Couple of ways:

if you always want to end on the tens,  just build into the wait loop a check for "00:00".

If you want it to be variable end time, pass the end time to the timer function.
Most timer calls have an optional parameter where you can pass an integer, or a void * pointer to anything.
0
 

Author Comment

by:VirtueTech
ID: 16837723
This just is not accurate enough. Is there a way to use the windows clock instead?
0
 
LVL 8

Accepted Solution

by:
krbatge earned 1600 total points
ID: 16837786
Well, you could always continue to set the timer to the time till the next 10 the same way you start it initially.

e.g.

void CHKVisionDlg::ResetTensStartTimer()
{
          time_t ltime;
          struct tm now;
          time(&ltime);
          now = *localtime(&ltime);
          int nMinsTillTen = (10 - (now.tm_min % 10));
          int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
          OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);
}

void CHKVisionDlg::OnStart()
{
     .
     .
     .

//    if (UseOnStartTimerOne == 0) {
          ResetTensStartTimer();
//     }
}

void CHKVisionDlg::OnTimer(...)
{
    .
    .
    .
    else if (nIDEvent == 15) // JLM
    {    
         KillTimer(OnStartTimerOne);
         OnStop();
         ResetTensStartTimer();
         OnStart();
    }
}
0
 

Author Comment

by:VirtueTech
ID: 16854889
Thanks guys.

I split the points and gave grg99 100 points because he helped spark some thought for me.

As for the solution I have tried in the past to just always use the re-sync timer function ...and it  didn't work. The problem was were I was starting the timer functinality.

Thanks everyone for your replies/time.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question