Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 

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