[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 715
  • Last Modified:

SetTimer() for delay

Hi,

   I want to write a delay function down to 1ms. Currently, I use SetTimer(timerId, timeout) to do this. Problem is, the timming seems correct only for "timeout > 100". Why is this happening, my code is like
this(simplified):


class NewDialog: public TDialog
{
public:
    NewDialog();
    ...
    ...

protected:
    int timenow;
    void EvTimer(uint);

    DECLARE_RESPONSE_TABLE(NewDialog);
};

DEFINE_RESPONSE_TABLE1(NewDialog, TDialog)
    EV_WM_TIMER,
END_RESPONSE_TABLE;

NewDialog::NewDialog()
{
    timenow = 0;
}

void NewDialog::SetupWindow()
{
    TDialog::SetupWindow();
    SetTimer(1, 1);
}

void NewDialog::EvTimer(uint)
{
    if(timenow++ == 1000)
    {
        MessageBox("Time out");
        timenow = 0;
    }
}


I compiled the code with Borland C++ 5.02.
The MessageBox takes > 10s to appear. What's wrong?
Or, is there any other ways to implement delay() under Win32?

Any help will be appreciated.

Thanks.
0
TanTT
Asked:
TanTT
1 Solution
 
gatkinsoCommented:
The Windows SetTimer function only has a resolution of about 11 ms.  For a higher resolution timer, I would suggest using an MCI timer (harder to do, and I am only about 50% sure how to do it), or perhaps spawn a "Timer" thread in which you loop continuously, sending a message every millisecond:

void TimerThreadProc(LONG lParam) {
 while (bRunning) {
  Sleep(1);  //Sleep() has a resolution of 1 ms (so "they" say)
  SendMessage(hTargetWnd,ID_YOURTIMEOUTMESSAGEID,lYourDataParam);
 }
}

I hope that this is not a real time application (otherwise you wouldn't be running Windows :)  ), as this code will be off a few microseconds in either direction.

For the MCI method, search the documentation for info on the following fragment:

MCIERROR mciSendCommand(MCIDEVICEID wDeviceID,
              MCI_SETTIMECODE,    //  <--- this is the key
              DWORD dwFlags,
              (DWORD) (LPMCI_GENERIC_PARMS) lpSetTimeCode);
0
 
AlexVirochovskyCommented:
Yes, gatkinso right, must use Pause command, but
must pay attention to 2 punkts:
1. This works only in thread !!!
2. You can not use Timer, but make Loop in you thread
 and Pause. For more details see Petzold's Book
"Programming in Windows"
This is example from 14 chapter:(multi2)

void Thread1 (PVOID pvoid)
     {
     PPARAMS pparams ;

     pparams = (PPARAMS) pvoid ;

     while (!pparams->bKill)
          {
             .... //you code
              Pause(1);
          }
     _endthread () ;
     }
Regards, Alex

0
 
TanTTAuthor Commented:
I checked the accuracy of Sleep() with following code:

   for(count = 0; count < 10000; count)
      Sleep(1);
   MessageBox("Timeout");

The messagebox took more than 20s to appear. Thus, it won't be accurate if I implement the code as stated.

The MCI part, however, I didn't test it since a lot of codes have to be modified.

My friend told me to use QueryPerformanceCounter() & QueryPerformanceFrequency() for high-resolution timer. The functions worked quite well. The messagebox took exactly 10s to appear on screen.

Thanks anyway.

0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now