Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Answer in this question contains DateTimePrecise class that should return current date with millisecond precision. But class is pretty bug and complicated. So I wrote my own version which seems work fine. If you see any problems with my code?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class DateTimePrecise
{
    private long startTick;
    private Stopwatch sw;

    public DateTimePrecise()
    {
        startTick = DateTime.Now.Ticks;
        sw = Stopwatch.StartNew();
    }

    public DateTime CurDateTime()
    {
        return new DateTime(startTick + sw.ElapsedTicks);
    }

}
}

I understand that my version is not accurate, meaning that actual system time may be less or more up to several milliseconds (±16 ms likely). But my version is still precise meaning that couple of measurements will defer at exactly spent milliseconds. And that's exactly what I need. I need precise but not necessary accurate clock because I only need to compare values between each other and I don't need exact current time up to milliseconds.

share|improve this question
    
You now need to be able to compare this instance to another or to any object, etc. so there are things like IComparable, IEquitable, ... –  Leonid Jul 22 '12 at 17:58
    
Reading your comment below, one thing doesn't make sense: what does current time have to do with plotting a graph? –  Groo Jul 23 '12 at 9:27
1  
Microsoft has an example of using the high-resolution timer. This timer provides accuracy to the millisecond. A sample implementation is available here: msdn.microsoft.com/en-us/library/aa964692(v=vs.85).aspx –  Reacher Gilt Jul 23 '12 at 16:29
    
@Groo because I need to see current time so I can go to trading terminal and to compare what I see on graph with what I see in terminal. –  javapowered Jul 24 '12 at 8:49
1  
You should describe your actual use case to get better suggestions, because I am pretty sure that this approach won't solve your problem. –  Groo Jul 24 '12 at 10:13
show 3 more comments

2 Answers 2

up vote 1 down vote accepted

You can't have a reliable 1 ms resolution timer like that.

Anyone who knows otherwise should paste a minimal code that runs for full 5 minutes, and outputs an array of ~ 5*60*1000 ms ticks with a max diff of 2.


Well, that being said, please consult my timer class and let me know if it's helpful for you:

public class TimerWrapper : ITimer
{
    #region DLL IMPORT
    [DllImport("WinMM.dll", SetLastError = true)]
    private static extern uint timeSetEvent(int msDelay, int msResolution,
                TimerEventHandler handler, ref int userCtx, int eventType);

    [DllImport("WinMM.dll", SetLastError = true)]
    static extern uint timeKillEvent(uint timerEventId);

    [DllImport("Winmm.dll")]
    private static extern int timeGetTime();
    #endregion

    public event Action<int> __Tick;
    public event Action __Stopped;

    public delegate void TimerEventHandler(uint id, uint msg, ref int userCtx,
        int rsv1, int rsv2);

    public void Stop()
    {
        timeKillEvent(m_fastTimer);
        InvokeStopped();
    }

    public void Start(int interval, int timeout)
    {
        m_res = 0;
        m_count = 0;
        _startCount = timeGetTime();
        m_maxCount = timeout * 1000 / interval;
        m_interval = interval;
        int myData = 0; // dummy data
        _thandler = new TimerEventHandler(tickHandler);
        m_fastTimer = timeSetEvent(interval, interval, _thandler,
            ref myData, 1); // type=periodic
    }

    private void InvokeTick(int t)
    {
        if (__Tick != null)
        {
            __Tick(t);
        }
    }

    private void InvokeStopped()
    {
        if (__Stopped != null)
        {
            __Stopped();
        }
    }

    private long m_maxCount;
    private int m_interval;
    private uint m_fastTimer;
    private long m_count;
    private int _startCount;
    private int _maxTimerTTL = 1000;    // ms
    private int m_res;
    private TimerEventHandler _thandler;

    private bool IsInfinite { get { return m_maxCount < 0; } }
    private bool IsRestarted { get { return m_interval <= 100 && m_interval >= 5; } }

    private void tickHandler(uint id, uint msg, ref int userCtx, int rsv1, int rsv2)
    {
        int span = timeGetTime() - _startCount;
        InvokeTick(span + m_res);

        if (m_count++ >= m_maxCount && !IsInfinite)
        {
            Stop();
        }
        else if (IsRestarted && span > _maxTimerTTL)
        {
            m_res += span;
            RestartTimer();
            _startCount = timeGetTime();
        }
    }

    private void RestartTimer()
    {
        int myData = 0; // dummy data
        timeKillEvent(m_fastTimer);
        m_fastTimer = timeSetEvent(m_interval, m_interval, new TimerEventHandler(tickHandler), ref myData, 1);  // type=periodic
    }
}

Interface:

public interface ITimer
{
    event Action<int> __Tick;
    event Action __Stopped;
    void Start(int interval, int timeout);
    void Stop();
}

Usage:

public static void Main()
{
    var barrier = new ManualResetEvent(false);
    var list = new List<int>();
    ITimer timer = new TimerWrapper();
    timer.__Tick += new Action<int> ( (i) => list.Add(i) );
    timer.__Stopped += new Action ( () => barrier.Set() );
    timer.Start(1, 5 * 60);
    barrier.WaitOne();
    foreach(var v in list)
        Console.WriteLine(v);
}
share|improve this answer
add comment

If you don't need a precise DateTime, only differences, then don't use DateTime at all. I think you should work only with TimeSpans.

This will avoid confusion, because with your class, it looks like DateTimePrecise .CurDateTime() is better than DateTime.Now, even when used once. If you only used TimeSpans, this wouldn't be a problem.

share|improve this answer
    
i'm using this datetimes to plot graphics in matlab. so I need "about" true value (16ms precision is ok) so I can understand where I am on the graphic. but I also need to distinguish dots close to each other because i do analyze trades that close to each other (sometimes i do trade every 1 ms) –  javapowered Jul 22 '12 at 14:09
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.