终端一体化运控平台
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

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