Click to See Complete Forum and Search --> : C# CreateTimerQueueTimer
AberAber
February 27th, 2008, 12:16 PM
I'm trying to make a periodic timer but this thing seriously just does not work. Maybe I'm getting the wrong signature when I try and use it in C#? It fires the callback immediately (despite it not being supposed to), then gets a memory write exception to 0x00000000.
NewTimer timer = new NewTimer(1000);
class NewTimer
{
DateTime start;
int ctr = 0;
[DllImport("kernel32.dll")]
private unsafe static extern int CreateTimerQueue();
[DllImport("kernel32.dll")]
private static unsafe extern bool CreateTimerQueueTimer(ref int* phNewTimer, int TimerQueue,
WaitOrTimerCallback Callback, object Parameter, long DueTime, long Period, uint Flags);
private delegate void TimeProc(long param, bool timeOrWaitFired);
internal unsafe NewTimer(long millis)
{
int queueHandler;
int* pointer = &queueHandler;
int handle = CreateTimerQueue();
WaitOrTimerCallback callback = new WaitOrTimerCallback(EventCallback);
object whatever = 0;
bool result = CreateTimerQueueTimer(ref pointer, handle, callback, whatever, 10000, 10000, 0);
start = DateTime.Now;
}
public void EventCallback(object param, bool timeOrWaitFired)
{
ctr++;
DateTime now = DateTime.Now;
TimeSpan diff = now - start;
Console.WriteLine(ctr / diff.TotalSeconds);
}
}
Mutant_Fruit
February 27th, 2008, 12:40 PM
What's the actual C declaration of the function you're calling?
AberAber
February 27th, 2008, 01:56 PM
BOOL WINAPI CreateTimerQueueTimer(
__out PHANDLE phNewTimer,
__in_opt HANDLE TimerQueue,
__in WAITORTIMERCALLBACK Callback,
__in_opt PVOID Parameter,
__in DWORD DueTime,
__in DWORD Period,
__in ULONG Flags
);
Mutant_Fruit
February 27th, 2008, 02:43 PM
Instead of passing a ref int*, which is an int**, you should pass an IntPtr.
private static unsafe extern bool CreateTimerQueueTimer(IntPtr phNewTimer, int TimerQueue....
AberAber
February 27th, 2008, 03:15 PM
Hi,
Unfortunately now it exceptions on the CreateTimerQueueTimer line.
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
class NewTimer
{
DateTime start;
int ctr = 0;
[DllImport("kernel32.dll")]
private unsafe static extern int CreateTimerQueue();
[DllImport("kernel32.dll")]
private static unsafe extern bool CreateTimerQueueTimer(IntPtr phNewTimer, int TimerQueue,
WaitOrTimerCallback Callback, object Parameter, long DueTime, long Period, uint Flags);
private delegate void TimeProc(long param, bool timeOrWaitFired);
internal unsafe NewTimer(long millis)
{
IntPtr pointer = new IntPtr();
int handle = CreateTimerQueue();
WaitOrTimerCallback callback = new WaitOrTimerCallback(EventCallback);
object whatever = 0;
bool result = CreateTimerQueueTimer(pointer, handle, callback, whatever, 10000, 10000, 0);
start = DateTime.Now;
}
public void EventCallback(object param, bool timeOrWaitFired)
{
ctr++;
DateTime now = DateTime.Now;
TimeSpan diff = now - start;
Console.WriteLine(ctr / diff.TotalSeconds);
}
wildfrog
February 27th, 2008, 03:52 PM
I'm not sure, but maybe it easier to use .Net Frameworks ThreadPool.RegisterWaitForSingleObject (http://msdn2.microsoft.com/en-us/library/aa332406(VS.71).aspx)?
- petter
AberAber
February 27th, 2008, 03:56 PM
Doesn't that have the same awful precision as DateTime.Now comparisons? It's something like 10 ms terribly inaccurately done, while the CreateTimer one is much more precise.
wildfrog
February 27th, 2008, 04:29 PM
AFAIK CreateTimerQueueTimer isn't regarded a high-resolution timer:
If the DueTime and Period parameters are both nonzero, the timer will be signaled first at the due time, then periodically. The callback is called every time the period elapses, whether or not the previous callback has finished executing. Callback functions are queued to the thread pool. These threads are subject to scheduling delays, so the timing can vary depending on what else is happening in the application or the system.
- petter
AberAber
February 28th, 2008, 08:15 AM
Do you have any solutions then? At least I should be able to use CreateTimerQueue timer to test it. I used setTimerQueue, which tested effectively at 1 ms timer, but it exceptioned randomly after about 30 seconds about writing to protected memory. I then discovered the timer was obsolete, and replaced by the one I put here.
Mutant_Fruit
February 28th, 2008, 10:24 AM
How accurate do you need? Are we talking microsecond accuracy? Millisecond accuracy? Nanosecond accuracy?
AberAber
February 29th, 2008, 10:45 AM
Probably microseconds is sufficient.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.