终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

211 line
8.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Collections.Concurrent;
  7. using System.Diagnostics;
  8. using System.Threading;
  9. using BPASmartClient.Message;
  10. namespace BPASmartClient.Helper
  11. {
  12. /// <summary>
  13. /// 线程管理
  14. /// </summary>
  15. public class ThreadManage : Singleton<ThreadManage>
  16. {
  17. string guid = "871d7e28-c413-4675-8d28-64e4dca4c2d3-";
  18. private static readonly object _lock = new object();
  19. StringBuilder callbackKey = new StringBuilder();
  20. List<string> keys = new List<string>();
  21. ConcurrentDictionary<string, Task> Threads = new ConcurrentDictionary<string, Task>();
  22. ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSources = new ConcurrentDictionary<string, CancellationTokenSource>();
  23. /// <summary>
  24. /// 停止指定任务
  25. /// </summary>
  26. /// <param name="key">任务名</param>
  27. /// <param name="ExitCallback">任务结束的回调</param>
  28. public void StopTask(string key, Action ExitCallback = null)
  29. {
  30. if (CancellationTokenSources.ContainsKey(guid + key))
  31. {
  32. CancellationTokenSources[guid + key]?.Cancel();
  33. ActionManage.GetInstance.Register(ExitCallback, guid + key);
  34. }
  35. else
  36. {
  37. if (ExitCallback != null) ExitCallback();
  38. }
  39. }
  40. /// <summary>
  41. /// 长任务,带 while true 的循环
  42. /// </summary>
  43. /// <param name="action"></param>
  44. /// <param name="key"></param>
  45. public void StartLong(Action action, string key, bool IsRestart = false, Action RunComplete = null)
  46. {
  47. if (!Threads.ContainsKey(guid + key))
  48. {
  49. CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
  50. bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
  51. {
  52. Thread.CurrentThread.Name = key;
  53. MessageLog.GetInstance.Show($"启动线程 【{key}】");
  54. ReStart:
  55. try
  56. {
  57. while (!CancellationTokenSources[guid + key].IsCancellationRequested)
  58. {
  59. if (action != null) action();
  60. }
  61. }
  62. catch (Exception ex)
  63. {
  64. MessageLog.GetInstance.ShowEx(ex.ToString());
  65. MessageLog.GetInstance.ShowEx(ex.Message);
  66. if (IsRestart)
  67. {
  68. Thread.Sleep(2000);
  69. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已重启");
  70. goto ReStart;
  71. }
  72. else
  73. {
  74. CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource temp);
  75. Threads.TryRemove(guid + key, out Task temp1);
  76. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已退出");
  77. }
  78. }
  79. }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
  80. {
  81. ThreadStatus(t, o.ToString());
  82. if (RunComplete != null) RunComplete();
  83. }), guid + key));
  84. }
  85. else MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
  86. }
  87. /// <summary>
  88. /// 不带 while true 的循环任务
  89. /// </summary>
  90. /// <param name="action"></param>
  91. /// <param name="key"></param>
  92. public void Start(Action action, string key, bool isRestart = false)
  93. {
  94. if (!Threads.ContainsKey(guid + key))
  95. {
  96. CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
  97. bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
  98. {
  99. Thread.CurrentThread.Name = key;
  100. MessageLog.GetInstance.Show($"启动线程 【{key}】");
  101. try
  102. {
  103. if (action != null) action();
  104. }
  105. catch (Exception ex)
  106. {
  107. MessageLog.GetInstance.ShowEx(ex.ToString());
  108. if (isRestart)
  109. {
  110. MessageLog.GetInstance.Show($"线程 【{key}】正在重启");
  111. CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource item1);
  112. Threads.TryRemove(guid + key, out Task item2);
  113. Start(action, key, isRestart);
  114. }
  115. else
  116. {
  117. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常");
  118. }
  119. }
  120. }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
  121. {
  122. ThreadStatus(t, o.ToString());
  123. }), guid + key));
  124. }
  125. else MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
  126. }
  127. private void ThreadStatus(Task task, string key)
  128. {
  129. bool IsRemove = false;
  130. string name = key.Substring(key.LastIndexOf('-') + 1);
  131. switch (task.Status)
  132. {
  133. case TaskStatus.RanToCompletion:
  134. MessageLog.GetInstance.Show($"线程【{name}】执行完成");
  135. IsRemove = true;
  136. break;
  137. case TaskStatus.Faulted:
  138. MessageLog.GetInstance.Show($"线程【{name}】执行异常,{task.Exception}");
  139. IsRemove = true;
  140. break;
  141. case TaskStatus.Canceled:
  142. MessageLog.GetInstance.Show($"线程【{name}】已取消");
  143. IsRemove = true;
  144. break;
  145. default:
  146. break;
  147. }
  148. if (IsRemove)
  149. {
  150. if (Threads.ContainsKey(key))
  151. Threads.TryRemove(key, out Task t);
  152. //Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName));
  153. if (CancellationTokenSources.ContainsKey(key))
  154. CancellationTokenSources.TryRemove(key, out CancellationTokenSource cts);
  155. //CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName));
  156. //keys.Remove(key);
  157. //if (keys != null && keys.Count == 0) ActionManage.GetInstance.Send(callbackKey.ToString());
  158. ActionManage.GetInstance.Send(key);
  159. }
  160. }
  161. /// <summary>
  162. /// 释放所有线程资源
  163. /// </summary>
  164. public void Dispose()
  165. {
  166. for (int i = 0; i < CancellationTokenSources.Count; i++)
  167. {
  168. CancellationTokenSources.ElementAt(i).Value.Cancel();
  169. }
  170. }
  171. /// <summary>
  172. /// 判断指定线程是否完成
  173. /// </summary>
  174. /// <param name="key"></param>
  175. /// <returns></returns>
  176. public bool IsComplete(string key)
  177. {
  178. if (Threads.ContainsKey(guid + key)) return Threads[guid + key].IsCompleted;
  179. return false;
  180. }
  181. /// <summary>
  182. /// 根据key获取取消状态,为start()开启的task在外部停止使用。
  183. /// </summary>
  184. /// <param name="key"></param>
  185. /// <returns></returns>
  186. public bool IsCanncel(string key)
  187. {
  188. if (CancellationTokenSources.ContainsKey(guid + key)) return CancellationTokenSources[guid + key].IsCancellationRequested;
  189. return false;
  190. }
  191. public bool IsContainsKey(string key)
  192. {
  193. return Threads.ContainsKey(guid + key);
  194. }
  195. }
  196. }