TimerManager.cs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using Common.Helper;
  5. using MongoDB.Bson;
  6. namespace Common.Base
  7. {
  8. public class TimerManager
  9. {
  10. private class Timer
  11. {
  12. public ObjectId Id { get; set; }
  13. public long Time { get; set; }
  14. public Action Action { get; set; }
  15. }
  16. private readonly Dictionary<ObjectId, Timer> timers = new Dictionary<ObjectId, Timer>();
  17. /// <summary>
  18. /// key: time, value: timer id
  19. /// </summary>
  20. private readonly MultiMap<long, ObjectId> timeGuid = new MultiMap<long, ObjectId>();
  21. private readonly Queue<long> timeoutTimer = new Queue<long>();
  22. public ObjectId Add(long time, Action action)
  23. {
  24. Timer timer = new Timer { Id = ObjectId.GenerateNewId(), Time = time, Action = action };
  25. this.timers[timer.Id] = timer;
  26. this.timeGuid.Add(timer.Time, timer.Id);
  27. return timer.Id;
  28. }
  29. public void Remove(ObjectId id)
  30. {
  31. Timer timer;
  32. if (!this.timers.TryGetValue(id, out timer))
  33. {
  34. return;
  35. }
  36. this.timers.Remove(timer.Id);
  37. this.timeGuid.Remove(timer.Time, timer.Id);
  38. }
  39. public Task<bool> Sleep(int time)
  40. {
  41. TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
  42. this.Add(TimeHelper.Now() + time, () => { tcs.SetResult(true); });
  43. return tcs.Task;
  44. }
  45. public void Refresh()
  46. {
  47. long timeNow = TimeHelper.Now();
  48. foreach (long time in this.timeGuid.Keys)
  49. {
  50. if (time > timeNow)
  51. {
  52. break;
  53. }
  54. this.timeoutTimer.Enqueue(time);
  55. }
  56. while (this.timeoutTimer.Count > 0)
  57. {
  58. long key = this.timeoutTimer.Dequeue();
  59. ObjectId[] timeoutIds = this.timeGuid.GetAll(key);
  60. foreach (ObjectId id in timeoutIds)
  61. {
  62. Timer timer;
  63. if (!this.timers.TryGetValue(id, out timer))
  64. {
  65. continue;
  66. }
  67. this.Remove(id);
  68. timer.Action();
  69. }
  70. }
  71. }
  72. }
  73. }