在某些高精度计时场景中,我们可能需要一个能够精确到微秒级别的时钟或定时器。虽然 C# 和 .NET 框架本身并不直接提供微秒级别的时钟,但我们可以利用 Stopwatch
类来创建一个高精度的时钟和定时器。本文将介绍如何实现一个微秒级的时钟,以及如何将其封装成一个类似 System.Timer
的功能。
首先,让我们实现一个基本的微秒级时钟:
C#using System;
using System.Diagnostics;
public class MicrosecondClock
{
private readonly Stopwatch stopwatch;
private readonly DateTime startTime;
public MicrosecondClock()
{
stopwatch = new Stopwatch();
startTime = DateTime.Now;
stopwatch.Start();
}
public DateTime Now
{
get
{
long ticks = stopwatch.Elapsed.Ticks;
return startTime.AddTicks(ticks);
}
}
public string GetFormattedTime()
{
DateTime now = Now;
long microseconds = stopwatch.Elapsed.Ticks / (TimeSpan.TicksPerMillisecond / 1000);
return $"{now:yyyy-MM-dd HH:mm:ss}.{microseconds:D6}";
}
}
这个 MicrosecondClock
类使用 Stopwatch
来测量经过的时间,精确到 ticks(1 tick = 100 纳秒)。它提供了两个主要方法:
Now
属性返回当前时间,精确到 tick。GetFormattedTime()
方法返回一个格式化的字符串,显示当前时间精确到微秒。接下来,我们将实现一个类似 System.Timer
的微秒级定时器:
C#using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
public class MicrosecondTimer : IDisposable
{
private readonly Stopwatch stopwatch;
private long interval;
private bool enabled;
private Task timerTask;
private CancellationTokenSource cancellationTokenSource;
public event EventHandler<MicrosecondTimerEventArgs> Elapsed;
public MicrosecondTimer()
{
stopwatch = new Stopwatch();
interval = Stopwatch.Frequency / 1000; // 默认1毫秒
enabled = false;
}
public bool Enabled
{
get => enabled;
set
{
if (enabled != value)
{
enabled = value;
if (enabled)
Start();
else
Stop();
}
}
}
public long Interval
{
get => interval * 1000000 / Stopwatch.Frequency;
set => interval = value * Stopwatch.Frequency / 1000000;
}
private void Start()
{
cancellationTokenSource = new CancellationTokenSource();
timerTask = Task.Run(TimerLoop, cancellationTokenSource.Token);
}
private void Stop()
{
cancellationTokenSource?.Cancel();
timerTask?.Wait();
}
private async Task TimerLoop()
{
stopwatch.Restart();
while (!cancellationTokenSource.Token.IsCancellationRequested)
{
long elapsedTicks = stopwatch.ElapsedTicks;
if (elapsedTicks >= interval)
{
OnElapsed(new MicrosecondTimerEventArgs(elapsedTicks * 1000000 / Stopwatch.Frequency));
stopwatch.Restart();
}
await Task.Delay(1);
}
}
protected virtual void OnElapsed(MicrosecondTimerEventArgs e)
{
Elapsed?.Invoke(this, e);
}
public void Dispose()
{
Stop();
cancellationTokenSource?.Dispose();
}
}
public class MicrosecondTimerEventArgs : EventArgs
{
public long ElapsedMicroseconds { get; }
public MicrosecondTimerEventArgs(long elapsedMicroseconds)
{
ElapsedMicroseconds = elapsedMicroseconds;
}
}
这个 MicrosecondTimer
类提供了以下功能:
Enabled
属性用于启动或停止定时器。Interval
属性设置定时器的间隔,以微秒为单位。Elapsed
事件在每次定时器触发时被引发。Task
和 CancellationTokenSource
来控制定时器的运行。下面是如何使用这些类的示例:
C#class Program
{
static void Main()
{
// 使用 MicrosecondClock
MicrosecondClock clock = new MicrosecondClock();
Console.WriteLine($"Current time: {clock.GetFormattedTime()}");
// 使用 MicrosecondTimer
using (var timer = new MicrosecondTimer())
{
timer.Interval = 1000; // 设置为1000微秒(1毫秒)
timer.Elapsed += (sender, e) =>
{
Console.WriteLine($"Timer elapsed: {e.ElapsedMicroseconds} microseconds");
};
timer.Enabled = true;
Console.WriteLine("Press any key to stop the timer...");
Console.ReadKey();
}
}
}
在使用这些高精度时钟和定时器时,需要注意以下几点:
MicrosecondTimer
在后台使用一个持续运行的任务,可能会消耗一定的系统资源。对于需要长时间运行或需要大量实例的场景,可能需要考虑更优化的实现。通过使用 Stopwatch
类和一些巧妙的编程技巧,我们可以在 C# 中实现微秒级的时钟和定时器。这些实现可以在需要高精度计时的场景中发挥作用,如性能测试、科学计算或某些实时系统。然而,在使用这些高精度工具时,务必要考虑到硬件和操作系统的限制,以及潜在的性能影响。
本文作者:rick
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!