Link to home
Start Free TrialLog in
Avatar of jeffiepoo
jeffiepooFlag for United States of America

asked on

C# Timer class equivalent in C++

Hey Experts,

Is there a C++ (Using Visual C++) equivalent for the Timer class in C#?

I need to run code in a separate thread after a certain amount of time.

Thanks for any help!

-Jeff
Avatar of jkr
jkr
Flag of Germany image

Yes there is a native version of timers (that's what C# is using in the background), see http://msdn.microsoft.com/en-us/library/windows/desktop/ms632592%28v=vs.85%29.aspx ("Timers"), you will find code samples at http://msdn.microsoft.com/en-us/library/windows/desktop/ms644901%28v=vs.85%29.aspx ("Using Timers"). These are the 'simpler' version of timers that use either callback functions or Windows messages, then there is also the more advaced concept of Waitable Timer Objects (http://msdn.microsoft.com/en-us/library/windows/desktop/ms687012%28v=vs.85%29.aspx). For these, you will find examples at http://www.codeproject.com/Articles/1236/Timers-Tutorial ("Timers Tutorial"). This article also covers your third option, the Multimedia Timers.
Oh, and here's a class wrapping the more complex timers up: http://www.codeproject.com/Articles/146617/Simple-C-Timer-Wrapper ("Simple C++ Timer Wrapper")

BTW, if you are using C++.NET, you might already be comfortable with this http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=VS.71%29.aspx ("Timer Class")
the simplest method is to call
Sleep(milliseconds);

Open in new window


in your thread.

if you need an absolute timer you would do like

SYSTEMTIME st = { 2013, 3, 5, 22, 13, 0, 0, 0 };
FILETIME ft;
SystemTimeToFileTime(&st, &ft);
HANDLE h = CreateWaitableTimer(NULL, FALSE);
SetWaitableTimer(h, (LARGE_INTEGER*)&ft,  0, NULL, NULL, FALSE);
WaitForSingleObject(h, INFINITE);

Open in new window


of course you need to add error handling to the above code.

Sara
Avatar of jeffiepoo

ASKER

I've been looking at SetTimer vs SetWaitableTimer. SetTimer seems to be a little simpler so I might use that.

Will the callback method be run on another thread? Any idea how this works?

What if I want the callback to modify data within the class it is in? Is that a problem?

Also, I can't block on the timer, I need to set it and forget it.

If not, I think this is my answer.

Another person recommended a TimerQueue which seems very hairy.

-Jeff
MSDN is unspecific about the thread context of the callback function used there, but since it is called asynchronously, you can assume it is a separate thread. However, there are two caveats:

- it is a 'plain' function or a static member, not a class' member.
- you can't pass any individual data, so it is hard to manipulate any class members

Furthermore, 'SetTimer()' requires applications that use it to run a window with a message queue, if you don't have one, this won't work. Adifferent approach would be creating a thread on your own that uses 'Sleep()', e.g.

class TheClass { // your class
public:

  void DoSomething();
};

struct ThreadArgs {

  TheClass* pClass;
  DWORD dwInterval;
};

DWORD WINAPI TimerThread ( LPVOID pv) {

  ThreadArgs* p = (ThreadArgs*) pv;

  for (;;) { // does not have to be a loop, just to demonstrate how to do that periodically

    Sleep(p->dwInterval);

    p->pClass->DoSomething();

  }

   return 0; // makes the compiler happy
};

//...

TheClass c;

ThreadArgs ta;

ta.pClass = &c;
ta.dwInterval = 5000; // 5s

DWORD dwTID;

HANDLE hThread = CreateThread(NULL, 0, TimerThread, (LPVOID) &ta, 0, &dwTID);

Open in new window

as told by jkr, SetTimer will invoke a message loop timer which will call the callback function from current message pump. therefore it is not running asynchronously in a thread but synchronously in the main (ui) thread. because of this you may not do any lengthy operation in the callback or even sleep cause that would freeze the screen and make the program non-responsive. but, of course you could communicate from OnTimer callback with a thread started prior to calling SetTimer. if doing so  the SetTimer/OnTimer is not simpler than SetWaitableTimer cause if it would require an additional synchronization with a thread. the SetTimer/OnTimer is good for periodical updating of controls, for example a progress counter. you also could start a thread from callback which did not require further synchronization bat calls back for example by posting messages to one of the active windows.

Sara
ASKER CERTIFIED SOLUTION
Avatar of jeffiepoo
jeffiepoo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
CreateTimerQueueTimer does everything I need, and in the manner I needed it. The other timers were complex as well, but didn't functionally work as well.