File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -152,10 +152,23 @@ internal int ProcessTimers()
152152
153153 if ( entry . IsRepeating && entry . Interval . HasValue )
154154 {
155- // Schedule next execution for interval timers
156- entry . ExecuteAt = DateTime . UtcNow . AddMilliseconds ( entry . Interval . Value ) ;
157-
158- var nextExecution = ( entry . ExecuteAt - DateTime . UtcNow ) . TotalMilliseconds ;
155+ // Schedule next execution based on the original scheduled time, not current time
156+ // This prevents timer drift caused by callback execution time
157+ var nextExecuteAt = entry . ExecuteAt . AddMilliseconds ( entry . Interval . Value ) ;
158+
159+ // If we've fallen behind (next execution is already in the past),
160+ // skip to the next future interval to avoid a backlog of immediate fires
161+ now = DateTime . UtcNow ;
162+ if ( nextExecuteAt <= now )
163+ {
164+ var missedMs = ( now - nextExecuteAt ) . TotalMilliseconds ;
165+ var intervalsToSkip = ( long ) Math . Ceiling ( missedMs / entry . Interval . Value ) ;
166+ nextExecuteAt = nextExecuteAt . AddMilliseconds ( intervalsToSkip * entry . Interval . Value ) ;
167+ }
168+
169+ entry . ExecuteAt = nextExecuteAt ;
170+
171+ var nextExecution = ( entry . ExecuteAt - now ) . TotalMilliseconds ;
159172 if ( nextExecution < nextTimerDelay ) nextTimerDelay = ( int ) Math . Ceiling ( nextExecution ) ;
160173 }
161174 else
You can’t perform that action at this time.
0 commit comments