在wpf开发中我们经常会通过弹窗给用户推送信息,有时候我们一些信息非常频繁,会出现弹窗轰炸的效果。
这时候我们可以把信息写到log里面,但通知到用户也是必要的,我们可以给相同的信息设置冷却时间和标识避免弹窗频繁弹出。
核心逻辑
- 给信息定义标识
- 记录此标识上一次弹窗时间
- 若在冷却时间内不弹窗,仅记录次数
这里我们的弹窗用的是Notification.Wpf,这个库是fork的,但更新得比较好,推荐!
实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| using Notification.Wpf;
namespace NotificationThrottle.Services { public class NotificationThrottle { private readonly Dictionary<string, TrackInfo> _trackInfo = new Dictionary<string, TrackInfo>(); private readonly TimeSpan _cooldown = TimeSpan.FromSeconds(10);
private readonly NotificationManager _notificationManager;
public NotificationThrottle(NotificationManager notificationManager) { _notificationManager = notificationManager; }
public void ShowThrottledNotification(string id, string message,NotificationType notificationType=NotificationType.Information) { if(!_trackInfo.TryGetValue(id, out TrackInfo trackInfoValue)) { trackInfoValue = new TrackInfo() { LastTime = DateTime.MinValue, Count = 1 }; _trackInfo[id] = trackInfoValue; }
TimeSpan elapsed = DateTime.Now - trackInfoValue.LastTime; if (elapsed < _cooldown) { trackInfoValue.Count++; return; }
_notificationManager.Show(Enum.GetName(typeof(NotificationType), notificationType), $"{message}, 期间尝试弹出{trackInfoValue.Count}次", notificationType);
trackInfoValue.LastTime = DateTime.Now; _trackInfo[id] = trackInfoValue; }
private class TrackInfo { public DateTime LastTime { get; set; } public int Count { get; set; } } } }
|
提示
如果冷却时间需要可配置的话推荐注册单例服务。
不需要配置的话可以写成扩展方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public static class NotificationManagerExtensions { private static readonly Dictionary<string, TrackInfo> _trackInfo = new Dictionary<string, TrackInfo>(); private static readonly TimeSpan _cooldown = TimeSpan.FromSeconds(10); public static void ShowThrottledNotification(this NotificationManager notificationManager, string id, string message, NotificationType notificationType = NotificationType.Information) { if (!_trackInfo.TryGetValue(id, out TrackInfo trackInfoValue)) { trackInfoValue = new TrackInfo() { LastTime = DateTime.MinValue, Count = 1 }; _trackInfo[id] = trackInfoValue; }
TimeSpan elapsed = DateTime.Now - trackInfoValue.LastTime; if (elapsed < _cooldown) { trackInfoValue.Count++; return; }
notificationManager.Show(Enum.GetName(typeof(NotificationType), notificationType), $"{message}, 期间尝试弹出{trackInfoValue.Count}次", notificationType);
trackInfoValue.LastTime = DateTime.Now; _trackInfo[id] = trackInfoValue; }
private class TrackInfo { public DateTime LastTime { get; set; } public int Count { get; set; } } }
|
优化逻辑
在原有设置冷却时间的基础上我们其实可以动态调整冷却时间,可以更灵活的处理高频信息。
思路:
根据弹出信息触发频率延长冷却时间。
需要加字段基础冷却时间、最长冷却时间、触发次数阈值、延长倍率。
当尝试弹出触发次数大于触发阈值时延长冷却时间,但为了避免无限延长冷却时间我们设置最长冷却时间。
代码地址