我能不能使这个TimerQueueTimer 类的性能更高

本文关键字:性能 TimerQueueTimer 能不能 | 更新日期: 2023-09-27 17:56:09

using System;
using System.Threading;
internal class TimerQueueTimer : IDisposable
{
    public TimerQueueTimer(int interval, int msBeforeFirstCall)
    {
        this.interval = interval;
        this.msBeforeFirstCall = msBeforeFirstCall;
        this.callback = this.ticked;
        this.isTheFirstTick = true;
        this.isStopped = true;
    }
    public event EventHandler Ticked;
    public void Start()
    {
        if (!this.isStopped)
        {
            return;
        }
        this.isTheFirstTick = true;
        this.isStopped = false;
        Computer.ChangeTimerResolutionTo(1);
        NativeMethods.CreateTimerQueueTimer(
            out this.handle,
            IntPtr.Zero,
            this.callback,
            IntPtr.Zero,
            (uint)this.msBeforeFirstCall,
            (uint)this.interval,
            CallbackExecution.ExecuteInTimerThread);
    }
    public void Stop()
    {
        if (this.isStopped)
        {
            return;
        }
        NativeMethods.DeleteTimerQueueTimer(
            IntPtr.Zero,
            this.handle,
            IntPtr.Zero);
        Computer.ClearTimerResolutionChangeTo(1);
        this.isStopped = true;
    }
    public void Dispose()
    {
        this.Stop();
    }
    private void ticked(IntPtr parameterPointer, bool timerOrWaitFired)
    {
        if (this.isStopped)
        {
            return;
        }
        if (this.isTheFirstTick)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
        }
        this.isTheFirstTick = false;
        var ticked = this.Ticked;
        if (ticked != null)
        {
            ticked(this, EventArgs.Empty);
        }
    }
    private IntPtr handle;
    private volatile bool isStopped;
    private volatile bool isTheFirstTick;
    private readonly WaitOrTimerDelegate callback;
    private readonly int interval;
    private readonly int msBeforeFirstCall;
}

(注:Computer.ChangeTimerResolutionTo()Computer.ClearTimerResolutionChangeTo()分别调用timeBeginPeriodtimeEndPeriod

问题:

  1. 回调在计时器的线程中运行,而不是在 ThreadPool 线程中运行。 只要回调函数速度快就可以了,对吧?
  2. 将回调线程(以及计时器线程)优先级设置为"最高"是否在性能方面有任何作用?
  3. 如果tickCount % interval == 0,是否最好使计时器间隔为 1ms 并计算滴答声,提高Ticked? 间隔较低的计时器是否更准确和精确?
  4. 是否有任何原因可能不如类似创建的timeSetEvent计时器准确和/或精确?

我问的原因是,当系统负载过重时,我们遇到了计时器回调偶尔延迟长达~50ms的问题。 与我们以前使用timeSetEvent时相比,感觉这种情况发生的频率更低了——尽管这可能只是一种错觉。 我知道Windows不是确定性的,所以我能做的只有这么多。 但是,我想确保我已经尽我所能使它尽可能高优先级。 我还能做什么吗?

我能不能使这个TimerQueueTimer 类的性能更高

我使用优先级队列来解决这个问题:队列的每个元素都包含回调地址(计时器例程),指向回调参数的指针以及将来应该触发的时间。

"时间"是优先级,这里的逻辑是有可能从另一个线程唤醒计时器线程。当另一个线程将回调添加到队列中时,计时器线程将唤醒并查找优先级队列的顶部元素,计算当前时间和存储在队列中的"时间"之间的差异,并休眠,直到超过计算的超时。

当计时器线程因超时而被唤醒时,它会从线程池启动新线程,从而调用回调。

我这里有一个计时器队列实现,它没有经过很好的测试,但您可以查看它是否有帮助。