25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.3 KiB

  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading;
  6. namespace DataVAPI.Tool
  7. {
  8. /// <summary>
  9. /// 线程集中处理委托
  10. /// </summary>
  11. /// <param name="action"></param>
  12. public delegate void ActionKeyHandle(string action);
  13. public delegate void ThreadExceptionHandle(string action, Exception ex);
  14. public delegate void ThreadExitHandle(string action);
  15. /// <summary>
  16. /// 执行器
  17. /// </summary>
  18. public class Executer : Singleton<Executer>
  19. {
  20. private System.Timers.Timer _timer4Monitor = new System.Timers.Timer(1000);
  21. private ConcurrentDictionary<string, Thread> _actions = new ConcurrentDictionary<string, Thread>();
  22. private object _async = new object();
  23. public event ThreadExceptionHandle OnThreadException;
  24. public event ThreadExitHandle ThreadExit;
  25. /// <summary>
  26. /// 构造器
  27. /// </summary>
  28. public Executer()
  29. {
  30. }
  31. /// <summary>
  32. ///
  33. /// </summary>
  34. public void Dispose()
  35. {
  36. _timer4Monitor.Stop();
  37. foreach (var th in _actions)
  38. {
  39. try { th.Value.Abort(); }
  40. catch (ThreadAbortException) { }
  41. }
  42. }
  43. /// <summary>
  44. ///
  45. /// </summary>
  46. /// <returns></returns>
  47. public List<Thread> GetActionInfos()
  48. {
  49. Monitor.TryEnter(_async, 200);
  50. var actionInfos = _actions.Values.ToList();
  51. Monitor.Exit(_async);
  52. return actionInfos;
  53. }
  54. /// <summary>
  55. ///
  56. /// </summary>
  57. /// <param name="key"></param>
  58. public void Abort(string key)
  59. {
  60. Monitor.TryEnter(_async, 200);
  61. if (_actions.ContainsKey(key))
  62. {
  63. try { _actions[key].Abort(); }
  64. catch (ThreadAbortException) { }
  65. }
  66. Monitor.Exit(_async);
  67. }
  68. /// <summary>
  69. ///
  70. /// </summary>
  71. /// <param name="key"></param>
  72. /// <returns></returns>
  73. public bool ContainsKey(string key)
  74. {
  75. Monitor.TryEnter(_async, 200);
  76. var item = _actions[key];
  77. Monitor.Exit(_async);
  78. if (null != item)
  79. {
  80. return true;
  81. }
  82. return false;
  83. }
  84. /// <summary>
  85. ///
  86. /// </summary>
  87. /// <param name="action"></param>
  88. /// <param name="name"></param>
  89. /// <param name="isBackground"></param>
  90. /// <param name="priority"></param>
  91. public void Start(Action action, string name, bool isBackground = false, ThreadPriority priority = ThreadPriority.Normal)
  92. {
  93. Thread thread = new Thread(() =>
  94. {
  95. try
  96. {
  97. action();
  98. ThreadExit?.Invoke(name);
  99. }
  100. catch (Exception ex)
  101. {
  102. OnThreadException?.Invoke(name, ex);
  103. }
  104. });
  105. thread.IsBackground = isBackground;
  106. thread.Priority = priority;
  107. thread.Name = name;
  108. thread.Start();
  109. Monitor.TryEnter(_async, 50);
  110. if (_actions.ContainsKey(name))
  111. {
  112. try { _actions[name].Abort(); }
  113. catch (ThreadAbortException) { }
  114. }
  115. _actions[name] = thread;
  116. Monitor.Exit(_async);
  117. }
  118. /// <summary>
  119. ///
  120. /// </summary>
  121. /// <param name="action"></param>
  122. /// <param name="timeout"></param>
  123. /// <returns></returns>
  124. public bool StartWhiteReturn(Func<bool> action, int timeout = 3)
  125. {
  126. DateTime beginTime = DateTime.Now;
  127. bool doResult = false;
  128. while (DateTime.Now.Subtract(beginTime).TotalSeconds <= 3 && !doResult)
  129. {
  130. doResult = action();
  131. }
  132. return doResult;
  133. }
  134. /// <summary>
  135. ///
  136. /// </summary>
  137. public event ActionKeyHandle ActionAbort;
  138. /// <summary>
  139. ///
  140. /// </summary>
  141. public event ActionKeyHandle ActionStarted;
  142. }
  143. }