public void PostTimeoutAfter( ICorrelatedMessage source, Guid targetId, long timeoutMs, Action <TimeoutMessage> timeoutAction) { Ensure.NotNull(timeoutAction, "timeoutAction"); var timeoutRequest = new TimeoutRequestNode( source, targetId, timeoutMs, timeoutAction); lock (_queueLock) { if (_queue.Count >= _queue.MaxSize) { _queue.Resize(_queue.MaxSize + 100); } _queue.Enqueue(timeoutRequest, timeoutMs); } if (_starving) { _msgAddEvent.Set(); } }
private void ReadFromQueue(object o) { Thread.BeginThreadAffinity(); // ensure we are not switching between OS threads. Required at least for v8. while (!_stop) { TimeoutRequestNode msg = null; try { var epochMs = EpochMsFromDateTime(DateTime.UtcNow); lock (_queueLock) _queue.TryPeek(out msg); if (msg == null) { _starving = true; _msgAddEvent.Wait(100); _msgAddEvent.Reset(); _starving = false; } else if (msg.TimeoutMs > epochMs) { _starving = true; _msgAddEvent.Wait((int)(msg.TimeoutMs - epochMs)); _msgAddEvent.Reset(); _starving = false; } else // epochMs >= msg.TimeoutMs { lock (_queueLock) _queue.TryDequeue(out msg); var overdueMs = (epochMs - msg.TimeoutMs); if (overdueMs > 100) { if (Log.LogLevel >= LogLevel.Info) { Log.Info("Message should have timed out at " + msg.TimeoutMs + ", but it's now " + epochMs + " which is " + overdueMs + " late"); } } msg.SendTimeout(); } } catch (Exception ex) { Log.ErrorException(ex, $"Error while processing message {msg} in queued handler TimeoutService."); } } _stopped.Set(); Thread.EndThreadAffinity(); }