private async Task RunCallbackAsync() { bool isTraceLogLevelEnabled = _logger.IsEnabled(LogLevel.Trace); if (_isRunning) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Exiting run callback because its already running, will run again immediately."); } _shouldRunAgainImmediately = true; return; } if (isTraceLogLevelEnabled) { _logger.LogTrace("Starting RunCallbackAsync"); } using (await _lock.LockAsync().AnyContext()) { if (_isRunning) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Exiting run callback because its already running, will run again immediately."); } _shouldRunAgainImmediately = true; return; } _last = SystemClock.UtcNow; } try { _isRunning = true; DateTime?next = null; try { next = await _timerCallback().AnyContext(); } catch (Exception ex) { if (_logger.IsEnabled(LogLevel.Error)) { _logger.LogError(ex, "Error running scheduled timer callback: {Message}", ex.Message); } _shouldRunAgainImmediately = true; } if (_minimumInterval > TimeSpan.Zero) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Sleeping for minimum interval: {Interval}", _minimumInterval); } await SystemClock.SleepAsync(_minimumInterval).AnyContext(); if (isTraceLogLevelEnabled) { _logger.LogTrace("Finished sleeping"); } } var nextRun = SystemClock.UtcNow.AddMilliseconds(10); if (_shouldRunAgainImmediately || next.HasValue && next.Value <= nextRun) { ScheduleNext(nextRun); } else if (next.HasValue) { ScheduleNext(next.Value); } } catch (Exception ex) { if (_logger.IsEnabled(LogLevel.Error)) { _logger.LogError(ex, "Error running schedule next callback: {Message}", ex.Message); } } finally { _isRunning = false; _shouldRunAgainImmediately = false; } if (isTraceLogLevelEnabled) { _logger.LogTrace("Finished RunCallbackAsync"); } }
private async Task RunCallbackAsync() { bool isTraceLogLevelEnabled = _logger.IsEnabled(0); if (_isRunning) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Exiting run callback because its already running, will run again immediately.", Array.Empty <object>()); } _shouldRunAgainImmediately = true; } else { if (isTraceLogLevelEnabled) { LoggerExtensions.LogTrace(_logger, "Starting RunCallbackAsync", Array.Empty <object>()); } using (await _lock.LockAsync().AnyContext()) { if (_isRunning) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Exiting run callback because its already running, will run again immediately.", Array.Empty <object>()); } _shouldRunAgainImmediately = true; return; } _last = SystemClock.UtcNow; } try { _isRunning = true; DateTime? next = null; Stopwatch sw = Stopwatch.StartNew(); try { next = await _timerCallback().AnyContext(); } catch (Exception ex) { if (_logger.IsEnabled(LogLevel.Error)) { LoggerExtensions.LogError(_logger, ex, "Error running scheduled timer callback: {Message}", new object[1] { ex.Message }); } _shouldRunAgainImmediately = true; } finally { sw.Stop(); if (isTraceLogLevelEnabled) { LoggerExtensions.LogTrace(_logger, "Callback took: {Elapsed:g}", new object[1] { sw.Elapsed }); } } if (_minimumInterval > TimeSpan.Zero) { if (isTraceLogLevelEnabled) { LoggerExtensions.LogTrace(_logger, "Sleeping for minimum interval: {Interval:g}", new object[1] { _minimumInterval }); } await SystemClock.SleepAsync(_minimumInterval, default(CancellationToken)).AnyContext(); if (isTraceLogLevelEnabled) { LoggerExtensions.LogTrace(_logger, "Finished sleeping", Array.Empty <object>()); } } DateTime dateTime = SystemClock.UtcNow.AddMilliseconds(10.0); if (_shouldRunAgainImmediately || (next.HasValue && next.Value <= dateTime)) { ScheduleNext(dateTime); } else if (next.HasValue) { ScheduleNext(next.Value); } } catch (Exception ex2) { if (_logger.IsEnabled(LogLevel.Error)) { LoggerExtensions.LogError(_logger, ex2, "Error running schedule next callback: {Message}", new object[1] { ex2.Message }); } } finally { _isRunning = false; _shouldRunAgainImmediately = false; } if (isTraceLogLevelEnabled) { LoggerExtensions.LogTrace(_logger, "Finished RunCallbackAsync", Array.Empty <object>()); } } }