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

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