C# 我可以让这个TimerQueueTimer类更有效吗?

C# 我可以让这个TimerQueueTimer类更有效吗?,c#,performance,timer,C#,Performance,Timer,(注意:Computer.changeTimerSolutionTo()和Computer.cleartimerSolutionChangeTo()分别调用timeBeginPeriod和timeEndPeriod) 问题: 回调正在计时器的线程中运行,而不是在线程池线程中运行。只要回调函数是快速的,就可以了,对吗 将回调线程(以及计时器线程)的优先级设置为最高会对性能产生影响吗 如果tickCount%interval==0,那么将计时器间隔设为1ms并计数滴答声,提高Ticked是否更好?低

(注意:
Computer.changeTimerSolutionTo()
Computer.cleartimerSolutionChangeTo()
分别调用
timeBeginPeriod
timeEndPeriod

问题:

  • 回调正在计时器的线程中运行,而不是在线程池线程中运行。只要回调函数是快速的,就可以了,对吗
  • 将回调线程(以及计时器线程)的优先级设置为最高会对性能产生影响吗
  • 如果
    tickCount%interval==0,那么将计时器间隔设为1ms并计数滴答声,提高
    Ticked
    是否更好?低间隔计时器是否更精确
  • 是否有任何原因导致其精度和/或精度低于类似创建的
    timeSetEvent
    计时器

  • 我问这个问题的原因是,当系统处于重载状态时,计时器回调偶尔会被延迟50毫秒。与我们之前使用的
    timeSetEvent
    相比,这种情况似乎不太常见——尽管这可能只是一种幻觉。我知道Windows不是确定性的,所以我只能做这么多。然而,我想确保我已经尽了我所能,使这个尽可能高的优先级。还有什么我可以做的吗?

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

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

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


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

    仅供参考:首先检查
    ticked==null
    ,只直接调用
    ticked
    事件,这并不是最好的做法。通常,局部变量的全部要点是避免竞争条件。@如果您认为我解决了您的问题,则可以删除-ve point,这将是非常好的选择:)感谢@ruffp编辑并使答案更具可读性。今后,我将确保给出明确的答案。
    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;
    }