src/Microsoft.IdentityModel.Tokens/EventBasedLRUCache.cs
/// <summary>
/// This is the delegate for the event queue task.
/// </summary>
This is the delegate for the event queue task.
This is the delegate for the event queue task .
private void EventQueueTaskAction()
        {
            Interlocked.Increment(ref _taskCount);
            while (!_shouldStopImmediately)
            {
                Interlocked.Exchange(ref _eventQueueTaskState, EventQueueTaskRunning);
                try
                {
                    if (_removeExpiredValues && DateTime.UtcNow >= _dueForExpiredValuesRemoval)
                    {
                        if (_maintainLRU)
                            RemoveExpiredValuesLRU();
                        else
                            RemoveExpiredValues();
                        _dueForExpiredValuesRemoval = DateTime.UtcNow.AddSeconds(_removeExpiredValuesIntervalInSeconds);
                    }
                    if (_eventQueue.TryDequeue(out var action))
                    {
                        action?.Invoke();
                    }
                    else if (DateTime.UtcNow > _eventQueueTaskStopTime) 
                    {
                        if (Interlocked.CompareExchange(ref _eventQueueTaskState, EventQueueTaskStopped, EventQueueTaskRunning) == EventQueueTaskRunning)
                            break;
                    }
                    else 
                    {
                        Thread.Sleep(_eventQueuePollingInterval);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.LogWarning(LogHelper.FormatInvariant(LogMessages.IDX10900, ex));
                }
            }
            Interlocked.Decrement(ref _taskCount);
        }
private void EventQueueTaskAction ( ) { Interlocked . Increment ( ref _taskCount ) ; while ( ! _shouldStopImmediately ) { Interlocked . Exchange ( ref _eventQueueTaskState , EventQueueTaskRunning ) ; try { if ( _removeExpiredValues && DateTime . UtcNow >= _dueForExpiredValuesRemoval ) { if ( _maintainLRU ) RemoveExpiredValuesLRU ( ) ; else RemoveExpiredValues ( ) ; _dueForExpiredValuesRemoval = DateTime . UtcNow . AddSeconds ( _removeExpiredValuesIntervalInSeconds ) ; } if ( _eventQueue . TryDequeue ( out var action ) ) { action ? . Invoke ( ) ; } else if ( DateTime . UtcNow > _eventQueueTaskStopTime ) { if ( Interlocked . CompareExchange ( ref _eventQueueTaskState , EventQueueTaskStopped , EventQueueTaskRunning ) == EventQueueTaskRunning ) break ; } else { Thread . Sleep ( _eventQueuePollingInterval ) ; } } catch ( Exception ex ) { LogHelper . LogWarning ( LogHelper . FormatInvariant ( LogMessages . IDX10900 , ex ) ) ; } } Interlocked . Decrement ( ref _taskCount ) ; }
This is the delegate for the event queue task.
This is the delegate for the event queue task .
// Keep running until the queue is empty or the AppDomain is about to be unloaded or the application is ready to exit. // always set the state to EventQueueTaskRunning in case it was set to EventQueueTaskDoNotStop // remove expired items if needed // process all events in the queue and exit // no more event to be processed, exit if expired // Setting _eventQueueTaskState = EventQueueTaskStopped if the _eventQueueTaskEndTime has past and _eventQueueTaskState == EventQueueTaskRunning. // This means no other thread came in and it is safe to end this task. // If another thread adds new events while this task is still running, it will set the _eventQueueTaskState = EventQueueTaskDoNotStop instead of starting a new task. // The Interlocked.CompareExchange() call below will not succeed and the loop continues (until the event queue is empty and the _eventQueueTaskEndTime expires again). // This should prevent a rare (but theoretically possible) scenario caused by context switching. // if empty, let the thread sleep for a specified number of milliseconds before attempting to retrieve another value from the queue