gpt4 book ai didi

c# - C# 中的高分辨率计时器

转载 作者:太空狗 更新时间:2023-10-29 22:18:58 26 4
gpt4 key购买 nike

是否有高分辨率计时器,每次计时器到时都会引发事件,就像 System.Timer 类一样?我需要一个高分辨率计时器来每毫秒 Elapse

我经常看到解释秒表可以测量高分辨率的帖子,但我不想测量时间,我想创建 1 毫秒的间隔。

.NET 中有什么东西吗?还是我要编写自己的高分辨率计时器?

最佳答案

据我所知,.NET 框架中没有内置任何内容。 Windows 具有通过 Multimedia Timer API 处理高分辨率计时器事件的机制。 .下面是我快速创建的一个示例,它似乎可以完成这项工作。好像也有很好的例子here .

我会注意到此 API 会更改系统范围的设置,这会降低系统性能,因此买家要当心。出于测试目的,我建议跟踪计时器触发的频率,以验证计时是否与您尝试模拟的设备相似。由于 Windows 不是实时操作系统,您系统上的负载可能会导致 MM 计时器延迟,从而导致 100 毫秒的间隔包含快速连续的 100 个事件,而不是 100 个事件间隔 1 毫秒。一些additional reading在 MM 定时器上。

class Program
{
static void Main(string[] args)
{
TestThreadingTimer();
TestMultimediaTimer();
}

private static void TestMultimediaTimer()
{
Stopwatch s = new Stopwatch();
using (var timer = new MultimediaTimer() { Interval = 1 })
{
timer.Elapsed += (o, e) => Console.WriteLine(s.ElapsedMilliseconds);
s.Start();
timer.Start();
Console.ReadKey();
timer.Stop();
}
}

private static void TestThreadingTimer()
{
Stopwatch s = new Stopwatch();
using (var timer = new Timer(o => Console.WriteLine(s.ElapsedMilliseconds), null, 0, 1))
{
s.Start();
Console.ReadKey();
}
}

}

public class MultimediaTimer : IDisposable
{
private bool disposed = false;
private int interval, resolution;
private UInt32 timerId;

// Hold the timer callback to prevent garbage collection.
private readonly MultimediaTimerCallback Callback;

public MultimediaTimer()
{
Callback = new MultimediaTimerCallback(TimerCallbackMethod);
Resolution = 5;
Interval = 10;
}

~MultimediaTimer()
{
Dispose(false);
}

public int Interval
{
get
{
return interval;
}
set
{
CheckDisposed();

if (value < 0)
throw new ArgumentOutOfRangeException("value");

interval = value;
if (Resolution > Interval)
Resolution = value;
}
}

// Note minimum resolution is 0, meaning highest possible resolution.
public int Resolution
{
get
{
return resolution;
}
set
{
CheckDisposed();

if (value < 0)
throw new ArgumentOutOfRangeException("value");

resolution = value;
}
}

public bool IsRunning
{
get { return timerId != 0; }
}

public void Start()
{
CheckDisposed();

if (IsRunning)
throw new InvalidOperationException("Timer is already running");

// Event type = 0, one off event
// Event type = 1, periodic event
UInt32 userCtx = 0;
timerId = NativeMethods.TimeSetEvent((uint)Interval, (uint)Resolution, Callback, ref userCtx, 1);
if (timerId == 0)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
}

public void Stop()
{
CheckDisposed();

if (!IsRunning)
throw new InvalidOperationException("Timer has not been started");

StopInternal();
}

private void StopInternal()
{
NativeMethods.TimeKillEvent(timerId);
timerId = 0;
}

public event EventHandler Elapsed;

public void Dispose()
{
Dispose(true);
}

private void TimerCallbackMethod(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2)
{
var handler = Elapsed;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}

private void CheckDisposed()
{
if (disposed)
throw new ObjectDisposedException("MultimediaTimer");
}

private void Dispose(bool disposing)
{
if (disposed)
return;

disposed = true;
if (IsRunning)
{
StopInternal();
}

if (disposing)
{
Elapsed = null;
GC.SuppressFinalize(this);
}
}
}

internal delegate void MultimediaTimerCallback(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2);

internal static class NativeMethods
{
[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")]
internal static extern UInt32 TimeSetEvent(UInt32 msDelay, UInt32 msResolution, MultimediaTimerCallback callback, ref UInt32 userCtx, UInt32 eventType);

[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")]
internal static extern void TimeKillEvent(UInt32 uTimerId);
}

关于c# - C# 中的高分辨率计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24839105/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com