I\'m writing trading software and need to QoS one method that should not be executed more often than 10 times per second. As I\'m begginer in C# and almost not familar with
There is always the System.Timer
timer.
That is probably easier to work with than the Stopwatch (which normally is used to measure how long time things take).
Code:
var timer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer using a lambda
timer.Elapsed += (o, e) => Console.WriteLine("Timer elapsed");
// Set the Interval to 100 ms
timer.Interval = 100;
// Start the timer.
timer.Enabled = true;
MSDN docs: http://msdn.microsoft.com/en-us/library/system.timers.timer(v=VS.100).aspx
Stopwatches and timers are fairly expensive objects to use. You could simply hold a DateTime object as a variable and perform a comparison.
DateTime lastCheck = DateTime.Now;
private void update()
{
// DateTime.Subtract returns a TimeSpan
int elapsed = DateTime.Now.Subtract(lastCheck).Milliseconds;
if (elapsed < 100)
{
Console.WriteLine("!skip update " + elapsed.ToString());
return;
} else
{
Console.WriteLine("!update");
lastCheck = DateTime.Now;
}
// do work here
}
Your technique of using Stopwatch
is the best solution to prevent the code from executing more frequently. As others have said, using a Timer
is a better solution if you want to make sure that the method is executed on a schedule.
Any approach based on DateTime
is fundamentally broken because it will fail when the date changes. This is especially noticeable during the Daylight Saving Time switches. When we "spring ahead", there's the potential of the update running twice in quick succession because the code thinks that it's been an hour since the previous update. That's not too bad. But when we "fall back", the update will be suspended for a full hour because the last update time is set an hour ahead.
The same kind of thing can happen, although not as severely, if your computer is set to update its time periodically from an NTP server. If the time is set ahead, then there is the potential for two updates to happen in quick succession. If the time is set back, there's the potential for updates not to happen for the amount of time the clock was set back.
There are ways around the problem (such as using the absolute value of the number of milliseconds), but then you're just putting a bandage on a broken solution. You shouldn't depend on DateTime
for intervals like this because your program isn't in control of the system clock--it can change at any time.
Stopwatch
is the only reasonable solution here because it depends on the CPU's performance counter, which only increases. You don't have the problems of somebody setting the counter back, and you don't have the rollover problems you would encounter with something like Environment.TickCount
.
There's some idea that Stopwatch
incurs a performance penalty that DateTime
doesn't. My testing shows that to be untrue.
I would not use a Stopwatch
or anything other Timer
-like. Instead just store the time of the method call and only execute the subsequent calls if the difference between the current and the stored time is bigger than 100ms.
You could implement a helper class to do this in a more general way:
public class TimedGate
{
private DateTime m_Last;
private TimeSpan m_Gap;
public TimedGate(TimeSpan gap)
{
m_Gap = gap;
}
public bool TryEnter()
{
DateTime now = DateTime.UtcNow;
if (now.Subtract(m_Last) > m_Gap)
{
m_LastEntered = now;
return true;
}
return false;
}
}
Use it like this:
TimedGate m_UpdateGate = new TimedGate(TimeSpan.FromMilliseconds(100));
private void Update()
{
if (m_UpdateGate.TryEnter())
{
Console.WriteLine("!update");
// do work here
}
else
{
Console.WriteLine("!skip update");
}
}