View difference between Paste ID: WymwySbr and E39dTeBT
SHOW: | | - or go back to the newest paste.
1
using System;
2
using System.Diagnostics;
3
using System.Runtime.InteropServices;
4
using System.Threading;
5
6-
    public class MicroTimer : IDisposable
6+
public class MicroTimer : IDisposable
7
{
8-
        [DllImport("winmm.dll")]
8+
	// Windows Multi-Media library to request a higher resolution period for the timer.
9-
        private static extern uint timeBeginPeriod(uint msec);
9+
	[DllImport("winmm.dll")]
10
	private static extern uint timeBeginPeriod(uint msec);
11-
        private static readonly decimal TicksPerMillisecond = Stopwatch.Frequency / 1000M;
11+
		
12-
        private decimal NextTime;
12+
	// Computes how many ticks are in each millisecond.
13-
        private Thread Iterator;
13+
	private static readonly decimal TicksPerMillisecond = Stopwatch.Frequency / 1000M;
14-
        private int Ms;
14+
	// Stores the next time the Timer should elapse at.
15
    private decimal NextTime;
16-
        public event ElapsedEventHandler Elapsed;
16+
	// The thread which to keep track of timing, as to not block.
17-
        public delegate void ElapsedEventHandler();
17+
    private Thread Iterator;
18-
        public decimal Interval { get; set; }
18+
	// Stores the number of millisecond the next iteration will wait for.
19
    private int Ms;
20-
        static MicroTimer()
20+
21
	// The Elapsed event, fired when the Timer has reached or exceeded its NextTIme value.
22-
            if (timeBeginPeriod(1) != 0) throw new Exception("High resolution timer not available.");
22+
    public event ElapsedEventHandler Elapsed;
23
    public delegate void ElapsedEventHandler();
24
	// The number of ticks each iteration will take.
25-
        public MicroTimer() => Interval = TicksPerMillisecond;
25+
    public decimal Interval { get; set; }
26
27-
        public void Start(bool initial = false)
27+
	// Static constructor to request high resolution from Operation System. Throws if fails.
28
    static MicroTimer()
29-
            if (Iterator == null)
29+
30
        if (timeBeginPeriod(1) != 0) throw new Exception("High resolution timer not available.");
31-
                NextTime = Stopwatch.GetTimestamp() + (initial ? 0 : Interval);
31+
    }
32-
                Iterator = new Thread(() =>
32+
33
	// Default constructor which initializes the interval to 1 second.
34-
                    while (true)
34+
    public MicroTimer() => Interval = TicksPerMillisecond;
35-
                    {
35+
36-
                        if ((Ms = (int)(Math.Floor((NextTime - Stopwatch.GetTimestamp()) / TicksPerMillisecond))) > 0) Thread.Sleep(Ms);
36+
	// Starts the Timer if it hasn't started already.
37-
                        while (Stopwatch.GetTimestamp() < NextTime) ;
37+
    public void Start(bool initial = false)
38-
                        Elapsed?.Invoke();
38+
39-
                        NextTime += Interval;
39+
        if (Iterator == null)
40-
                    }
40+
41-
                })
41+
			// Sets the NextTime to the current time with the addition of the Interval (ticks per iteration) if specified.
42
            NextTime = Stopwatch.GetTimestamp() + (initial ? 0 : Interval);
43-
                    Priority = ThreadPriority.Highest,
43+
			// Initializes a new thread
44-
                    IsBackground = true
44+
            Iterator = new Thread(() =>
45-
                };
45+
46-
                Iterator.Start();
46+
				// Infinite loop to track time.
47-
            }
47+
				while (true)
48
                {
49
					// Assigns Ms to how much time in millisecond until NextTime is reached and if that evaluation is greater than 0. If it is, sleep for that amount in milliseconds.
50-
        public void Stop()
50+
                    if ((Ms = (int)(Math.Floor((NextTime - Stopwatch.GetTimestamp()) / TicksPerMillisecond))) > 0) Thread.Sleep(Ms);
51
					// Poll with the remaining left over Ticks (sub millisecond precision).
52-
            if (Iterator != null)
52+
                    while (Stopwatch.GetTimestamp() < NextTime) ;
53
					// Fire Elapsed Event if not null.
54-
                Iterator.Abort();
54+
                    Elapsed?.Invoke();
55-
                Iterator = null;
55+
					// Set the NextTime to the next iteration.
56-
            }
56+
					NextTime += Interval;
57
				}
58
			})
59-
        public void Dispose() => Iterator?.Abort();
59+
			{
60-
    }
60+
				Priority = ThreadPriority.Highest, // Have this thread at a high priority.
61
				IsBackground = true // Prevent thread from still running after application has closed.
62
			};
63
			Iterator.Start(); // Starts the Thread.
64
		}
65
	}
66
67
	// Stops the Thread and nulls it.
68
    public void Stop()
69
    {
70
		if (Iterator != null)
71
        {
72
            Iterator.Abort();
73
            Iterator = null;
74
        }
75
    }
76
77
	// Disposes this object (implemented to the using statement can be used).
78
	public void Dispose() => Iterator?.Abort();
79
}