I use this in my Blazor application, letting other services send errors or warnings to this AlertService. The service triggers an update of a component which simply displays the messages, errors in red warnings in yellow.
While getting no new warnings, the existing warnings should be deleted, every 5 seconds one less warning being displayed. Same goes for errors.
When a new warning comes in, the timer restarts (so when the service was 1 second before deleting a warning, that timer is now void and the new timer starts with 5 seconds again).
This is my class, I feel there must be a better way but I haven't figured it out yet:
public class AlertService
{
private readonly ObservableCollection<string> errors = new ObservableCollection<string>();
private readonly ObservableCollection<string> warnings = new ObservableCollection<string>();
private object? talkingStickErrors;
private object? talkingStickWarnings;
public ReadOnlyObservableCollection<string> Errors { get; }
public ReadOnlyObservableCollection<string> Warnings { get; }
public AlertService()
{
Errors = new ReadOnlyObservableCollection<string>(errors);
Warnings = new ReadOnlyObservableCollection<string>(warnings);
}
public void Error(string message)
{
Console.WriteLine($"Error: {message}");
errors.Add(message);
StartErrorTimer();
}
private void StartErrorTimer()
{
talkingStickErrors = new object();
RemoveErrorAfterDelay(talkingStickErrors);
}
private async void RemoveErrorAfterDelay(object localTalkingStick)
{
while (true)
{
await Task.Delay(5000);
if (localTalkingStick != talkingStickErrors || !errors.Any()) return;
errors.RemoveAt(0);
}
}
public void Warning(string message)
{
Console.WriteLine($"Warning: {message}");
warnings.Add(message);
StartWarningTimer();
}
private void StartWarningTimer()
{
talkingStickWarnings = new object();
RemoveWarningAfterDelay(talkingStickWarnings);
}
private async void RemoveWarningAfterDelay(object localTalkingStick)
{
while (true)
{
await Task.Delay(5000);
if (localTalkingStick != talkingStickWarnings || !warnings.Any()) return;
warnings.RemoveAt(0);
}
}
}
Also I couldn't think of a better word for the talking sticks. They're not exactly locks.
Update: No more talking sticks, it now just reused the last message it received.
Update 2: Talking sticks again, as string have no unique identity.
Update 3: Instead of an extra event, the alerts are now in ObservableCollections. I keep receiving stuff about encapsulation and Rx. ould appreciate someone helping me to DRY this.