首頁 >後端開發 >C++ >如何在 C# 中建立具有基於事件的間隔訊號的高解析度計時器?

如何在 C# 中建立具有基於事件的間隔訊號的高解析度計時器?

Susan Sarandon
Susan Sarandon原創
2025-01-17 10:51:10553瀏覽

How Can I Create a High-Resolution Timer with Event-Based Interval Signaling in C#?

使用 C# 中的事件處理建立精確的高解析度計時器

本文詳細介紹如何用 C# 建立一個高解析度計時器,該計時器以指定的時間間隔觸發事件,從而提供比標準 System.Timer 類別更精細的控制。 我們將探索現有 .NET 選項的局限性,並使用 Windows 多媒體計時器 API 提出解決方案。

雖然 Stopwatch 類別提供高解析度時間測量,但它並不是為以精確間隔觸發事件而設計的。 .NET 框架本身缺乏直接滿足我們需求的架構。 因此,我們將利用針對事件計時進行了最佳化的 Windows 多媒體計時器 API。

使用多媒體計時器 API 實現高解析度計時器

以下是利用多媒體計時器 API 的 C# 實作:

<code class="language-csharp">using System;
using System.Runtime.InteropServices;

class MultimediaTimer : IDisposable
{
    private bool disposed = false;
    private int interval, resolution;
    private uint timerId;
    private readonly MultimediaTimerCallback Callback;

    public delegate void MultimediaTimerCallback(uint uTimerID, uint uMsg, IntPtr dwUser, uint dw1, uint dw2);
    public event EventHandler<EventArgs> TimerElapsed;

    public MultimediaTimer()
    {
        Callback = new MultimediaTimerCallback(TimerCallbackMethod);
        Resolution = 5; // Default resolution (milliseconds)
        Interval = 10; // Default interval (milliseconds)
    }

    ~MultimediaTimer() { Dispose(false); }

    public int Interval
    {
        get { return interval; }
        set
        {
            CheckDisposed();
            if (value > 0) interval = value;
        }
    }

    public int Resolution
    {
        get { return resolution; }
        set
        {
            CheckDisposed();
            if (value > 0 && value <= interval) resolution = value;
        }
    }

    public void Start()
    {
        CheckDisposed();
        uint result = timeSetEvent((uint)interval, (uint)resolution, Callback, IntPtr.Zero, 1);
        if (result == 0) throw new Exception("Failed to start timer.");
        timerId = result;
    }

    public void Stop()
    {
        CheckDisposed();
        if (timerId != 0) timeKillEvent(timerId);
        timerId = 0;
    }


    private void TimerCallbackMethod(uint uTimerID, uint uMsg, IntPtr dwUser, uint dw1, uint dw2)
    {
        TimerElapsed?.Invoke(this, EventArgs.Empty);
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            Stop();
            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    [DllImport("winmm.dll")]
    private static extern uint timeSetEvent(uint uDelay, uint uResolution, MultimediaTimerCallback lpTimeProc, IntPtr dwUser, uint fuEvent);

    [DllImport("winmm.dll")]
    private static extern uint timeKillEvent(uint uTimerID);
}</code>

重要注意事項:

多媒體定時器 API 與系統範圍的設定互動;調整可能會影響系統效能。 監視計時器頻率以確保其與目標間隔相符。 請記住,Windows 不是即時作業系統,因此系統負載可能會影響計時器的準確性。

結論

多媒體計時器 API 提供了一種強大的機制,用於在 C# 中使用基於事件的訊號建立高解析度計時器,解決精確計時至關重要的場景。 雖然不是本機 .NET 功能,但其功能使其成為滿足特定計時要求的寶貴工具。

以上是如何在 C# 中建立具有基於事件的間隔訊號的高解析度計時器?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn