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