编辑
2025-02-03
C# 应用
00
请注意,本文编写于 92 天前,最后修改于 92 天前,其中某些信息可能已经过时。

目录

1. 微秒时钟的实现
2. 微秒定时器的实现
3. 使用示例
4. 注意事项
结论

在某些高精度计时场景中,我们可能需要一个能够精确到微秒级别的时钟或定时器。虽然 C# 和 .NET 框架本身并不直接提供微秒级别的时钟,但我们可以利用 Stopwatch 类来创建一个高精度的时钟和定时器。本文将介绍如何实现一个微秒级的时钟,以及如何将其封装成一个类似 System.Timer 的功能。

1. 微秒时钟的实现

首先,让我们实现一个基本的微秒级时钟:

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() 方法返回一个格式化的字符串,显示当前时间精确到微秒。

2. 微秒定时器的实现

接下来,我们将实现一个类似 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 事件在每次定时器触发时被引发。
  • 使用 TaskCancellationTokenSource 来控制定时器的运行。

3. 使用示例

下面是如何使用这些类的示例:

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(); } } }

image.png

4. 注意事项

在使用这些高精度时钟和定时器时,需要注意以下几点:

  1. 实际精度受限于硬件和操作系统。虽然代码可以提供微秒级的精度,但不同系统的实际表现可能有所不同。
  2. 对于非常短的时间间隔(如几微秒),可能无法保证准确性,因为事件处理和任务调度本身就需要一定的时间。
  3. MicrosecondTimer 在后台使用一个持续运行的任务,可能会消耗一定的系统资源。对于需要长时间运行或需要大量实例的场景,可能需要考虑更优化的实现。
  4. 在多线程环境中使用时,需要注意事件处理程序的线程安全性。
  5. 长时间运行可能会积累误差。对于需要长期精确计时的应用,可能需要定期与系统时钟同步。

结论

通过使用 Stopwatch 类和一些巧妙的编程技巧,我们可以在 C# 中实现微秒级的时钟和定时器。这些实现可以在需要高精度计时的场景中发挥作用,如性能测试、科学计算或某些实时系统。然而,在使用这些高精度工具时,务必要考虑到硬件和操作系统的限制,以及潜在的性能影响。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!