Event Throttle
Event Throttle
Section titled “Event Throttle”When publishing events rapidly (e.g. search text changed, sensor data updates, UI gestures), you often don’t want every single event to trigger handler execution. The [Throttle] attribute implements a debounce pattern — only the last event in a time window is actually processed.
This is particularly useful for scenarios like:
- Search-as-you-type — only search after the user stops typing
- Sensor data — avoid overwhelming handlers with rapid sensor readings
- UI events — debounce resize, scroll, or input change events
-
Register the throttle event middleware in your host startup:
services.AddShinyMediator(cfg => cfg.AddThrottleEventMiddleware()); -
Mark your event handler method with the
[Throttle]attribute. The handler class must bepartial:[MediatorSingleton]public partial class SearchChangedHandler : IEventHandler<SearchChangedEvent>{[Throttle(500)] // 500 millisecondspublic async Task Handle(SearchChangedEvent @event, IMediatorContext context, CancellationToken ct){// This only executes after 500ms of no new SearchChangedEvent publicationsawait PerformSearch(@event.Query);}}
How It Works
Section titled “How It Works”When an event is published and the handler has a [Throttle] attribute:
- The middleware starts a timer for the specified delay (in milliseconds)
- If the same event is published again before the timer expires, the timer resets and the previous event is discarded
- Only after the full delay passes with no new events does the handler execute with the most recent event
This means rapid-fire events result in a single handler execution with the latest data.
Example — Search Debounce
Section titled “Example — Search Debounce”public record SearchChangedEvent(string Query) : IEvent;
[MediatorSingleton]public partial class SearchHandler : IEventHandler<SearchChangedEvent>{ readonly ISearchService searchService;
public SearchHandler(ISearchService searchService) { this.searchService = searchService; }
[Throttle(300)] // wait 300ms after last keystroke public async Task Handle(SearchChangedEvent @event, IMediatorContext context, CancellationToken ct) { var results = await this.searchService.Search(@event.Query, ct); // update UI with results }}If the throttle delay is set to 0 or less, the middleware will execute the handler immediately without any throttling.