M
MM
Hi,
I have imported the Multimedia timer funcs from "winmm.dll" and setup a c#
class with the TimerEventHandler:-
class MSecTmer
{
ulong count; // holds tick count of timer
<stuff>
private void tickHandler(int id, int msg, int userdata, int r1, int r2)
{
count++; // private ulong holding tick count
// now call listeners (from other classes) waiting on the given time
period
if (onTimePeriod != null)
onTimePeriod();
}
It works to a point. The listeners get called for a certain number of
iterations and then a MemoryAccessViolation exception occurs - always at the
same number of iterations. I really know very little about the
InteropServices namespace and about wrapping dll functions. I read somewhere
in the docs that the callback should not include any system calls, so I
commented out all but the increment and it *appeared* to work without
problems for a good 15 minutes.
private void tickHandler(int id, int msg, int callback, int r1, int r2)
{
count++; // private ulong holding tick count
// now call listeners waiting on the given time period
//if (onTimePeriod != null)
// onTimePeriod();
}
Adding....
{
count++; // private ulong holding tick count
Console.WriteLine(count);
}
caused the same problem as mentioned above but after a different number of
iterations. It seems to me that the thread is running out of stack/heap
space or something or a bad pointer somewhere - but where!? Any ideas what's
going wrong and how-to fix it? Thanks! matt.
Here's whole class...
//*******************************************************************
// Based on LP TimerTest
// a test application for .NET timers
// Copyright: Luc Pattyn, January 2007
// This code is freely available for any non-commercial use.
//*******************************************************************
using System;
using System.Collections; // ArrayList
using System.Text;
using System.Runtime.InteropServices; // DllImport
using System.Threading;
namespace Clocks
{
using TCount = System.Int64; // type to store tick counts
using TRes = System.UInt32; // timer resolution
public class MSecTimer
{
public delegate void TimePeriodHandler();
public event TimePeriodHandler onTimePeriod;
private int msecTimer;
TRes minMSec = 0;
TRes maxMSec = 0;
private TCount count;
private uint interval;
private DateTime start;
private DateTime stop;
public MSecTimer(TRes msecs)
{
GetCapabilities();
if ((msecs < minMSec) || (msecs > maxMSec))
throw new ArgumentOutOfRangeException("Timer period out of range");
else
{
interval = msecs;
}
}
private void GetCapabilities() {
TimeCaps timeCaps=new TimeCaps(0, 0);
uint result=timeGetDevCaps(out timeCaps, Marshal.SizeOf(timeCaps));
if (result!=0)
Console.WriteLine("timeGetDevCaps result="+result);
minMSec=timeCaps.minimum;
maxMSec=timeCaps.maximum;
}
public void Start() {
msecTimer=timeSetEvent(interval, interval, new
TimerEventHandler(tickHandler),
0, 1); // type=periodic
}
public void Stop()
{ timeKillEvent(msecTimer); }
private void tickHandler(int id, int msg, int userCtx, int rsv1, int rsv2)
{
count++;
if (onTimePeriod != null)
onTimePeriod();
}
[DllImport("Winmm.dll")]
private static extern int timeGetTime();
[DllImport("winmm.dll")]
private static extern uint timeGetDevCaps(out TimeCaps timeCaps, int size);
struct TimeCaps {
public uint minimum;
public uint maximum;
public TimeCaps(uint minimum, uint maximum) {
this.minimum=minimum;
this.maximum=maximum;
}
}
[DllImport("WinMM.dll", SetLastError=true)]
private static extern int timeSetEvent(uint msDelay, uint msResolution,
TimerEventHandler handler, int userCtx, int eventType);
[DllImport("WinMM.dll", SetLastError=true)]
static extern int timeKillEvent(int timerEventId);
public delegate void TimerEventHandler(int id, int msg, int userCtx,
int rsv1, int rsv2);
}
}
I have imported the Multimedia timer funcs from "winmm.dll" and setup a c#
class with the TimerEventHandler:-
class MSecTmer
{
ulong count; // holds tick count of timer
<stuff>
private void tickHandler(int id, int msg, int userdata, int r1, int r2)
{
count++; // private ulong holding tick count
// now call listeners (from other classes) waiting on the given time
period
if (onTimePeriod != null)
onTimePeriod();
}
It works to a point. The listeners get called for a certain number of
iterations and then a MemoryAccessViolation exception occurs - always at the
same number of iterations. I really know very little about the
InteropServices namespace and about wrapping dll functions. I read somewhere
in the docs that the callback should not include any system calls, so I
commented out all but the increment and it *appeared* to work without
problems for a good 15 minutes.
private void tickHandler(int id, int msg, int callback, int r1, int r2)
{
count++; // private ulong holding tick count
// now call listeners waiting on the given time period
//if (onTimePeriod != null)
// onTimePeriod();
}
Adding....
{
count++; // private ulong holding tick count
Console.WriteLine(count);
}
caused the same problem as mentioned above but after a different number of
iterations. It seems to me that the thread is running out of stack/heap
space or something or a bad pointer somewhere - but where!? Any ideas what's
going wrong and how-to fix it? Thanks! matt.
Here's whole class...
//*******************************************************************
// Based on LP TimerTest
// a test application for .NET timers
// Copyright: Luc Pattyn, January 2007
// This code is freely available for any non-commercial use.
//*******************************************************************
using System;
using System.Collections; // ArrayList
using System.Text;
using System.Runtime.InteropServices; // DllImport
using System.Threading;
namespace Clocks
{
using TCount = System.Int64; // type to store tick counts
using TRes = System.UInt32; // timer resolution
public class MSecTimer
{
public delegate void TimePeriodHandler();
public event TimePeriodHandler onTimePeriod;
private int msecTimer;
TRes minMSec = 0;
TRes maxMSec = 0;
private TCount count;
private uint interval;
private DateTime start;
private DateTime stop;
public MSecTimer(TRes msecs)
{
GetCapabilities();
if ((msecs < minMSec) || (msecs > maxMSec))
throw new ArgumentOutOfRangeException("Timer period out of range");
else
{
interval = msecs;
}
}
private void GetCapabilities() {
TimeCaps timeCaps=new TimeCaps(0, 0);
uint result=timeGetDevCaps(out timeCaps, Marshal.SizeOf(timeCaps));
if (result!=0)
Console.WriteLine("timeGetDevCaps result="+result);
minMSec=timeCaps.minimum;
maxMSec=timeCaps.maximum;
}
public void Start() {
msecTimer=timeSetEvent(interval, interval, new
TimerEventHandler(tickHandler),
0, 1); // type=periodic
}
public void Stop()
{ timeKillEvent(msecTimer); }
private void tickHandler(int id, int msg, int userCtx, int rsv1, int rsv2)
{
count++;
if (onTimePeriod != null)
onTimePeriod();
}
[DllImport("Winmm.dll")]
private static extern int timeGetTime();
[DllImport("winmm.dll")]
private static extern uint timeGetDevCaps(out TimeCaps timeCaps, int size);
struct TimeCaps {
public uint minimum;
public uint maximum;
public TimeCaps(uint minimum, uint maximum) {
this.minimum=minimum;
this.maximum=maximum;
}
}
[DllImport("WinMM.dll", SetLastError=true)]
private static extern int timeSetEvent(uint msDelay, uint msResolution,
TimerEventHandler handler, int userCtx, int eventType);
[DllImport("WinMM.dll", SetLastError=true)]
static extern int timeKillEvent(int timerEventId);
public delegate void TimerEventHandler(int id, int msg, int userCtx,
int rsv1, int rsv2);
}
}