终端一体化运控平台
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.
 
 
 

178 lines
6.9 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. CancellationTokenSources[guid + key]?.Cancel();
  32. ActionManage.GetInstance.Register(ExitCallback, guid + key);
  33. }
  34. /// <summary>
  35. /// 长任务,带 while true 的循环
  36. /// </summary>
  37. /// <param name="action"></param>
  38. /// <param name="key"></param>
  39. public void StartLong(Action action, string key, bool IsRestart = false, Action RunComplete = null)
  40. {
  41. CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
  42. bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
  43. {
  44. ReStart:
  45. try
  46. {
  47. while (!CancellationTokenSources[guid + key].IsCancellationRequested)
  48. {
  49. if (action != null) action();
  50. }
  51. }
  52. catch (Exception ex)
  53. {
  54. MessageLog.GetInstance.ShowEx(ex.ToString());
  55. if (IsRestart)
  56. {
  57. Thread.Sleep(2000);
  58. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已重启");
  59. goto ReStart;
  60. }
  61. else
  62. {
  63. CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource temp);
  64. Threads.TryRemove(guid + key, out Task temp1);
  65. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已退出");
  66. }
  67. }
  68. }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
  69. {
  70. ThreadStatus(t, o.ToString());
  71. if (RunComplete != null) RunComplete();
  72. }), guid + key));
  73. MessageLog.GetInstance.Show($"启动线程 【{key}】");
  74. if (!result) MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
  75. }
  76. /// <summary>
  77. /// 不带 while true 的循环任务
  78. /// </summary>
  79. /// <param name="action"></param>
  80. /// <param name="key"></param>
  81. public void Start(Action action, string key, bool isRestart = true)
  82. {
  83. MessageLog.GetInstance.Show($"线程 【{key}】启动");
  84. CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
  85. bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
  86. {
  87. try
  88. {
  89. if (action != null) action();
  90. }
  91. catch (Exception ex)
  92. {
  93. MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常");
  94. if (isRestart)
  95. {
  96. MessageLog.GetInstance.Show($"线程 【{key}】正在重启");
  97. CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource item1);
  98. Threads.TryRemove(guid + key, out Task item2);
  99. Start(action, key, isRestart);
  100. }
  101. }
  102. }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
  103. {
  104. ThreadStatus(t, o.ToString());
  105. }), guid + key));
  106. if (!result) MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
  107. }
  108. private void ThreadStatus(Task task, string key)
  109. {
  110. bool IsRemove = false;
  111. string name = key.Substring(key.LastIndexOf('-') + 1);
  112. switch (task.Status)
  113. {
  114. case TaskStatus.RanToCompletion:
  115. MessageLog.GetInstance.Show($"线程【{name}】执行完成");
  116. IsRemove = true;
  117. break;
  118. case TaskStatus.Faulted:
  119. MessageLog.GetInstance.Show($"线程【{name}】执行异常,{task.Exception}");
  120. IsRemove = true;
  121. break;
  122. case TaskStatus.Canceled:
  123. MessageLog.GetInstance.Show($"线程【{name}】已取消");
  124. IsRemove = true;
  125. break;
  126. default:
  127. break;
  128. }
  129. if (IsRemove)
  130. {
  131. if (Threads.ContainsKey(key))
  132. Threads.TryRemove(key, out Task t);
  133. //Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName));
  134. if (CancellationTokenSources.ContainsKey(key))
  135. CancellationTokenSources.TryRemove(key, out CancellationTokenSource cts);
  136. //CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName));
  137. //keys.Remove(key);
  138. //if (keys != null && keys.Count == 0) ActionManage.GetInstance.Send(callbackKey.ToString());
  139. ActionManage.GetInstance.Send(key);
  140. }
  141. }
  142. /// <summary>
  143. /// 释放所有线程资源
  144. /// </summary>
  145. public void Dispose()
  146. {
  147. for (int i = 0; i < CancellationTokenSources.Count; i++)
  148. {
  149. CancellationTokenSources.ElementAt(i).Value.Cancel();
  150. }
  151. }
  152. /// <summary>
  153. /// 判断指定线程是否完成
  154. /// </summary>
  155. /// <param name="key"></param>
  156. /// <returns></returns>
  157. public bool IsComplete(string key)
  158. {
  159. if (Threads.ContainsKey(guid + key)) return Threads[guid + key].IsCompleted;
  160. return false;
  161. }
  162. }
  163. }