RenderTimer.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using Avalonia.Rendering;
  2. using System;
  3. using System.Threading;
  4. using System.Timers;
  5. namespace Ryujinx.Ava.Ui.Controls
  6. {
  7. internal class RenderTimer : IRenderTimer, IDisposable
  8. {
  9. public event Action<TimeSpan> Tick
  10. {
  11. add
  12. {
  13. _tick += value;
  14. if (_subscriberCount++ == 0)
  15. {
  16. Start();
  17. }
  18. }
  19. remove
  20. {
  21. if (--_subscriberCount == 0)
  22. {
  23. Stop();
  24. }
  25. _tick -= value;
  26. }
  27. }
  28. private Thread _tickThread;
  29. private readonly System.Timers.Timer _timer;
  30. private Action<TimeSpan> _tick;
  31. private int _subscriberCount;
  32. private bool _isRunning;
  33. private AutoResetEvent _resetEvent;
  34. public RenderTimer()
  35. {
  36. _timer = new System.Timers.Timer(15);
  37. _resetEvent = new AutoResetEvent(true);
  38. _timer.Elapsed += Timer_Elapsed;
  39. }
  40. private void Timer_Elapsed(object sender, ElapsedEventArgs e)
  41. {
  42. TickNow();
  43. }
  44. public void Start()
  45. {
  46. _timer.Start();
  47. if (_tickThread == null)
  48. {
  49. _tickThread = new Thread(RunTick);
  50. _tickThread.Name = "RenderTimerTickThread";
  51. _tickThread.IsBackground = true;
  52. _isRunning = true;
  53. _tickThread.Start();
  54. }
  55. }
  56. public void RunTick()
  57. {
  58. while (_isRunning)
  59. {
  60. _resetEvent.WaitOne();
  61. _tick?.Invoke(TimeSpan.FromMilliseconds(Environment.TickCount));
  62. }
  63. }
  64. public void TickNow()
  65. {
  66. lock (_timer)
  67. {
  68. _resetEvent.Set();
  69. }
  70. }
  71. public void Stop()
  72. {
  73. _timer.Stop();
  74. }
  75. public void Dispose()
  76. {
  77. _timer.Elapsed -= Timer_Elapsed;
  78. _timer.Stop();
  79. _isRunning = false;
  80. _resetEvent.Set();
  81. _tickThread.Join();
  82. _resetEvent.Dispose();
  83. }
  84. }
  85. }