TimerManager.cs 2.1 KB

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