1 /// <summary> 2 /// 提供计时器服务 3 /// </summary> 4 public class TimerService 5 { 6 private static TimerService _Instance = null; 7 8 public static TimerService Instance 9 { 10 get 11 { 12 if (_Instance == null) 13 { 14 //实例化对象,并启动计时器服务 15 _Instance = new TimerService(); 16 _Instance.timer = new System.Timers.Timer(); 17 _Instance.timer.Interval = 1000; 18 _Instance.timer.Elapsed += _Instance.Timer_Elapsed; 19 _Instance.timer.Start(); 20 } 21 return _Instance; 22 } 23 } 24 25 /// <summary> 26 /// 定时器读写锁 27 /// </summary> 28 private UsingLock<Object> Lock = new UsingLock<object>(); 29 30 /// <summary> 31 /// 已注册的事件列表 32 /// </summary> 33 private List<TimerEventInfomation> SubscribedEvents = new List<TimerEventInfomation>(); 34 35 /// <summary> 36 /// 计时器,每秒计时一次 37 /// </summary> 38 private System.Timers.Timer timer = new System.Timers.Timer(); 39 40 /// <summary> 41 /// 获取当前时间戳 42 /// </summary> 43 /// <returns></returns> 44 private long GetTime() 45 { 46 return GetTime(DateTime.Now); 47 } 48 49 /// <summary> 50 /// 获取指定日期时间的时间戳 51 /// </summary> 52 /// <param name="time"></param> 53 /// <returns></returns> 54 public static long GetTime(DateTime time) 55 { 56 return Convert.ToInt32(time.Subtract(DateTime.Parse("1970-01-01")).TotalSeconds); 57 } 58 59 /// <summary> 60 /// 每秒触发一次该事件 61 /// </summary> 62 /// <param name="sender"></param> 63 /// <param name="e"></param> 64 private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 65 { 66 var time = GetTime(); 67 using (Lock.Write()) 68 { 69 var triggers = this.SubscribedEvents.Where(t => t.EventTime == time).ToList(); 70 foreach (var item in triggers) 71 { 72 //异步执行回调 73 item.EventCallback?.BeginInvoke(item, new AsyncCallback((d) => { }), null); 74 } 75 //移除全部本次已回调的对象列表 76 foreach (var item in triggers) 77 { 78 this.SubscribedEvents.Remove(item); 79 } 80 } 81 } 82 83 /// <summary> 84 /// 添加一个事件到计时器 85 /// </summary> 86 /// <param name="info"></param> 87 public void Add(TimerEventInfomation info) 88 { 89 using (Lock.Write()) 90 { 91 if (info.EventTime <= GetTime()) 92 { 93 return; 94 } 95 Logs.Info($"为活动{info.ActiveID}新增计时器 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(info)); 96 this.SubscribedEvents.Add(info); 97 } 98 } 99 100 /// <summary> 101 /// 无则新增,有则更新,新增返回true,更新返回false 102 /// </summary> 103 /// <param name="info"></param> 104 public bool Set(TimerEventInfomation info) 105 { 106 using (Lock.Write()) 107 { 108 var obj = this.SubscribedEvents.Where(t => t.ActiveID == info.ActiveID && t.Category == info.Category).FirstOrDefault(); 109 if (obj == null) 110 { 111 obj.EventTime = info.EventTime; 112 obj.callbackObject = info.callbackObject; 113 obj.EventCallback = info.EventCallback; 114 Logs.Info($"为活动{info.ActiveID}更新计时器 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(info)); 115 return false; 116 } 117 else 118 { 119 this.SubscribedEvents.Add(info); 120 Logs.Info($"为活动{info.ActiveID}新增计时器 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(info)); 121 return true; 122 } 123 } 124 } 125 126 /// <summary> 127 /// 清空指定活动的计时器 128 /// </summary> 129 public int Remove(int ActiveID) 130 { 131 using (Lock.Write()) 132 { 133 var Removes = this.SubscribedEvents.FindAll(t => t.ActiveID == ActiveID).ToList(); 134 if (Removes != null && Removes.Count > 0) 135 { 136 Logs.Info($"移除活动{ActiveID}全部计时器 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(Removes)); 137 } 138 return this.SubscribedEvents.RemoveAll(t => t.ActiveID == ActiveID); 139 } 140 } 141 142 /// <summary> 143 /// 移除掉指定类别的计时器,通常应用在举牌倒计时器,或者报名倒计时器,报名人满即将开始时自动清除报名倒计时器,或者活动成功结束后需要清理掉倒计时器 144 /// </summary> 145 /// <param name="ActiveID"></param> 146 /// <param name="category"></param> 147 public int Remove(int ActiveID, TimerEventInfomationCategorys category) 148 { 149 using (Lock.Write()) 150 { 151 return this.SubscribedEvents.RemoveAll(t => t.ActiveID == ActiveID && t.Category == category); 152 } 153 } 154 155 /// <summary> 156 /// 重载版本 157 /// </summary> 158 /// <param name="ActiveID"></param> 159 /// <param name="eventTime"></param> 160 /// <param name="sender"></param> 161 /// <param name="callback"></param> 162 public void Add(int ActiveID, DateTime eventTime, object sender, Action<Object> callback) 163 { 164 if (eventTime <= DateTime.Now) { return; } 165 using (Lock.Write()) 166 { 167 var info = new TimerEventInfomation() { ActiveID = ActiveID, EventTime = GetTime(eventTime), callbackObject = sender, EventCallback = callback }; 168 Logs.Info($"为活动{info.ActiveID}新增计时器 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(info)); 169 this.SubscribedEvents.Add(info); 170 } 171 } 172 173 /// <summary> 174 /// 用于重置符合指定条件的计时器计时时间 175 /// </summary> 176 /// <param name="ActiveID"></param> 177 /// <param name="category"></param> 178 /// <param name="time"></param> 179 public void ResetTime(int ActiveID, TimerEventInfomationCategorys category, DateTime time) 180 { 181 if (time <= DateTime.Now) { return; } 182 using (Lock.Write()) 183 { 184 var ms = this.SubscribedEvents.Where(t => t.ActiveID == ActiveID && t.Category == category).ToList(); 185 ms.ForEach(new Action<TimerEventInfomation>((t) => 186 { 187 t.EventTime = GetTime(time); 188 })); 189 Logs.Info($"为活动{ActiveID}更新类别{category.ToString()}计时器时间 -> " + Newtonsoft.Json.JsonConvert.SerializeObject(ms)); 190 } 191 } 192 193 /// <summary> 194 /// 计时器事件消息对象 195 /// </summary> 196 public class TimerEventInfomation 197 { 198 /// <summary> 199 /// 关联此事件的活动ID,用于批量重置或清除指定活动的全部事件 200 /// </summary> 201 public int ActiveID { get; set; } 202 203 /// <summary> 204 /// 标识,用于对计时器事件归类,方便通过该标识结合 205 /// </summary> 206 public TimerEventInfomationCategorys Category { get; set; } = TimerEventInfomationCategorys.通用; 207 208 /// <summary> 209 /// 事件时间,指定事件触发的具体时间 210 /// </summary> 211 public long EventTime { get; set; } 212 213 /// <summary> 214 /// 回调时的参数对象 215 /// </summary> 216 public Object callbackObject = null; 217 218 /// <summary> 219 /// 定时器自动触发的回调事件,当事件引发时,自动触发该回调 220 /// </summary> 221 public Action<Object> EventCallback { get; set; } 222 } 223 224 /// <summary> 225 /// 归类枚举 226 /// </summary> 227 public enum TimerEventInfomationCategorys 228 { 229 通用 = 0, 230 /// <summary> 231 /// 表明活动已经开始,举牌进行中,等待目标时间表明倒计时时间已到 232 /// </summary> 233 落拍倒计时 = 2, 234 /// <summary> 235 /// 应用于定时开拍类活动,表示定时开拍,非定拍类活动不会使用到此枚举 236 /// </summary> 237 定拍倒计时 = 3, 238 /// <summary> 239 /// 开拍倒计时,指活动正式开始前的30秒倒计时期间,定时该计时器用于处理活动正式开始 240 /// </summary> 241 开拍倒计时 = 4, 242 /// <summary> 243 /// 托管自动举牌,人工出价类,每次有人出价时,自动重置,用于从托管用户中获取一个用户自动执行举牌,时间为倒计时剩余3秒时。举牌的同时自动重置。 244 /// </summary> 245 托管自动举牌 = 5, 246 /// <summary> 247 /// 提供给新活动自动轮询的计时器对象 248 /// </summary> 249 新活动轮询 = 6 250 } 251 }
原文地址:https://www.cnblogs.com/soleds/p/11619389.html
时间: 2024-10-24 15:06:29