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.
 
 

141 lines
5.1 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 ThreadOperate
  15. {
  16. private volatile static ThreadOperate _Instance;
  17. public static ThreadOperate GetInstance => _Instance ?? (_Instance = new ThreadOperate());
  18. private ThreadOperate() { }
  19. string guid = "871d7e28-c413-4675-8d28-64e4dca4c2d3-";
  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="taskName">任务名</param>
  26. /// <param name="ExitCallback">任务结束的回调</param>
  27. public void StopTask(string taskName, Action ExitCallback = null)
  28. {
  29. if (CancellationTokenSources.ContainsKey(guid + taskName))
  30. CancellationTokenSources[guid + taskName]?.Cancel();
  31. ActionOperate.GetInstance.Register(ExitCallback, guid + taskName);
  32. }
  33. /// <summary>
  34. /// 长任务,带 while true 的循环
  35. /// </summary>
  36. /// <param name="action"></param>
  37. /// <param name="TaskName"></param>
  38. public void StartLong(Action action, string TaskName, Action RunComplete = null)
  39. {
  40. CancellationTokenSources.TryAdd(guid + TaskName, new CancellationTokenSource());
  41. bool result = Threads.TryAdd(guid + TaskName, Task.Factory.StartNew(new Action(() =>
  42. {
  43. while (!CancellationTokenSources[guid + TaskName].IsCancellationRequested)
  44. {
  45. if (action != null) action();
  46. }
  47. }), CancellationTokenSources[guid + TaskName].Token).ContinueWith(new Action<Task, object>((t, o) =>
  48. {
  49. ThreadStatus(t, o.ToString());
  50. if (RunComplete != null) RunComplete();
  51. }), guid + TaskName));
  52. MessageLog.GetInstance.Show($"启动线程 【{TaskName}】");
  53. if (!result) MessageLog.GetInstance.Show($"【{TaskName}】任务已存在,请检查 TaskName");
  54. }
  55. /// <summary>
  56. /// 不带 while true 的循环任务
  57. /// </summary>
  58. /// <param name="action"></param>
  59. /// <param name="TaskName"></param>
  60. public void Start(Action action, string TaskName)
  61. {
  62. CancellationTokenSources.TryAdd(guid + TaskName, new CancellationTokenSource());
  63. bool result = Threads.TryAdd(guid + TaskName, Task.Factory.StartNew(new Action(() =>
  64. {
  65. action();
  66. }), CancellationTokenSources[guid + TaskName].Token).ContinueWith(new Action<Task, object>((t, o) =>
  67. {
  68. ThreadStatus(t, o.ToString());
  69. }), guid + TaskName));
  70. if (!result) MessageLog.GetInstance.Show($"【{TaskName}】任务已存在,请检查 TaskName");
  71. }
  72. private void ThreadStatus(Task task, string TaskName)
  73. {
  74. bool IsRemove = false;
  75. string name = TaskName.Substring(TaskName.LastIndexOf('-') + 1);
  76. switch (task.Status)
  77. {
  78. case TaskStatus.RanToCompletion:
  79. MessageLog.GetInstance.Show($"线程【{name}】执行完成");
  80. IsRemove = true;
  81. break;
  82. case TaskStatus.Faulted:
  83. MessageLog.GetInstance.Show($"线程【{name}】执行异常,{task.Exception}");
  84. IsRemove = true;
  85. break;
  86. case TaskStatus.Canceled:
  87. MessageLog.GetInstance.Show($"线程【{name}】已取消");
  88. IsRemove = true;
  89. break;
  90. default:
  91. break;
  92. }
  93. if (IsRemove)
  94. {
  95. Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName));
  96. CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName));
  97. ActionOperate.GetInstance.Send(TaskName);
  98. }
  99. }
  100. /// <summary>
  101. /// 释放所有线程资源
  102. /// </summary>
  103. public void Dispose()
  104. {
  105. for (int i = 0; i < CancellationTokenSources.Count; i++)
  106. {
  107. CancellationTokenSources.ElementAt(i).Value.Cancel();
  108. }
  109. }
  110. /// <summary>
  111. /// 判断指定线程是否完成
  112. /// </summary>
  113. /// <param name="TaskName"></param>
  114. /// <returns></returns>
  115. public bool IsComplete(string TaskName)
  116. {
  117. if (Threads.ContainsKey(guid + TaskName))
  118. {
  119. return Threads[guid + TaskName].IsCompleted;
  120. }
  121. else
  122. {
  123. return false;
  124. }
  125. }
  126. }
  127. }