Skip to content

Commit 499dbb4

Browse files
committed
Try and fix a edge case where a timer could be fired earlier than the next run time and it scheduling was cancelled.
1 parent 57ac047 commit 499dbb4

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

src/Foundatio/Utility/ScheduledTimer.cs

+14-1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ private async Task RunCallbackAsync()
102102
return;
103103
}
104104

105+
// If the callback runs before the next time, then store it here before we reset it and use it for scheduling.
106+
DateTime? nextTimeOverride = null;
107+
105108
if (isTraceLogLevelEnabled) _logger.LogTrace("Starting RunCallbackAsync");
106109
using (await _lock.LockAsync().AnyContext())
107110
{
@@ -115,6 +118,13 @@ private async Task RunCallbackAsync()
115118
}
116119

117120
_last = SystemClock.UtcNow;
121+
if (SystemClock.UtcNow < _next)
122+
{
123+
_logger.LogWarning("ScheduleNext RunCallbackAsync was called before next run time {NextRun:O}, setting next to current time and rescheduling", _next);
124+
nextTimeOverride = _next;
125+
_next = SystemClock.UtcNow;
126+
_shouldRunAgainImmediately = true;
127+
}
118128
}
119129

120130
try
@@ -147,7 +157,10 @@ private async Task RunCallbackAsync()
147157
if (isTraceLogLevelEnabled) _logger.LogTrace("Finished sleeping");
148158
}
149159

150-
var nextRun = SystemClock.UtcNow.AddMilliseconds(10);
160+
var nextRun = SystemClock.UtcNow.AddMilliseconds(10);
161+
if (nextRun < nextTimeOverride)
162+
nextRun = nextTimeOverride.Value;
163+
151164
if (_shouldRunAgainImmediately || next.HasValue && next.Value <= nextRun)
152165
ScheduleNext(nextRun);
153166
else if (next.HasValue)

0 commit comments

Comments
 (0)