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.
 
 

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