See here:
http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=570
You can also use the Multimedia timer:
[CODE]
using System;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
namespace Multimedia
{
public enum TimerMode
{
OneShot,
Periodic
};
public delegate void TimerCallback(object state);
[StructLayout(LayoutKind.Sequential)]
public struct TimerCaps
{
public int periodMin;
public int periodMax;
}
public sealed class Timer : IDisposable
{
private delegate void TimeProc(int id, int msg, int user, int param1,
int param2);
[DllImport("winmm.dll")]
private static extern int timeGetDevCaps(ref TimerCaps caps,
int sizeOfTimerCaps);
[DllImport("winmm.dll")]
private static extern int timeSetEvent(int delay, int resolution,
TimeProc timeProc, int user, int mode);
[DllImport("winmm.dll")]
private static extern int timeKillEvent(int id);
private int timerID;
private TimerMode mode;
private int period;
private int resolution;
private bool running;
private TimeProc timeProcPeriodic;
private TimeProc timeProcOneShot;
private TimerCallback callback;
private object state;
private static TimerCaps caps;
private static ResourceManager resManager;
static Timer()
{
timeGetDevCaps(ref caps, Marshal.SizeOf(caps));
resManager = new ResourceManager("Multimedia.Resource",
Assembly.GetExecutingAssembly());
}
public Timer(TimerCallback callback, object state, int period,
int resolution)
{
this.callback = callback;
this.state = state;
timeProcPeriodic = new TimeProc(OnTimerPeriodicEvent);
timeProcOneShot = new TimeProc(OnTimerOneShotEvent);
Mode = TimerMode.Periodic;
Period = period;
Resolution = resolution;
running = false;
}
public Timer(TimerCallback callback, object state, int period,
int resolution, TimerMode mode)
{
this.callback = callback;
this.state = state;
timeProcPeriodic = new TimeProc(OnTimerPeriodicEvent);
timeProcOneShot = new TimeProc(OnTimerOneShotEvent);
Mode = mode;
Period = period;
Resolution = resolution;
running = false;
}
~Timer()
{
if(running)
{
Stop();
}
}
public void Start()
{
if(running)
{
Stop();
}
if(mode == TimerMode.Periodic)
{
timerID = timeSetEvent(Period, Resolution, timeProcPeriodic, 0,
(int)Mode);
}
else
{
timerID = timeSetEvent(Period, Resolution, timeProcOneShot, 0,
(int)Mode);
}
if(timerID != 0)
{
running = true;
}
else
{
string msg = resManager.GetString("TimerStartFailed");
throw new TimerStartException(msg);
}
}
public void Stop()
{
if(running)
{
timeKillEvent(timerID);
running = false;
}
}
public bool IsRunning()
{
return running;
}
private void OnTimerPeriodicEvent(int id, int msg, int user,
int param1, int param2)
{
callback(state);
}
private void OnTimerOneShotEvent(int id, int msg, int user, int param1,
int param2)
{
callback(state);
Stop();
}
public TimerMode Mode
{
get
{
return mode;
}
set
{
mode = value;
// If the timer is running.
if(IsRunning())
{
// Stop and restart timer.
Stop();
Start();
}
}
}
public int Period
{
get
{
return period;
}
set
{
if(value >= caps.periodMin && value <= caps.periodMax)
{
period = value;
if(IsRunning())
{
Stop();
Start();
}
}
else
{
Stop();
string msg = resManager.GetString("TimerPeriodOutOfRange");
throw new ArgumentOutOfRangeException("Period", value, msg);
}
}
}
public int Resolution
{
get
{
return resolution;
}
set
{
if(value >= 0)
{
resolution = value;
if(IsRunning())
{
Stop();
Start();
}
}
else
{
Stop();
string msg = resManager.GetString("TimerResolutionOutOfRange");
throw new ArgumentOutOfRangeException("Resolution", value, msg);
}
}
}
public static TimerCaps Capabilities
{
get
{
return caps;
}
}
#region IDisposable Members
public void Dispose()
{
if(running)
{
Stop();
}
}
#endregion
}
public class TimerStartException : ApplicationException
{
public TimerStartException(string message) : base(message)
{
}
}
}
[/CODE]