|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Collections.Concurrent;
- using System.Diagnostics;
- using System.Threading;
-
-
- namespace BPASmartClient.Helper
- {
- /// <summary>
- /// 线程管理
- /// </summary>
- public class ThreadManage : Singleton<ThreadManage>
- {
- string guid = "871d7e28-c413-4675-8d28-64e4dca4c2d3-";
- private static readonly object _lock = new object();
- StringBuilder callbackKey = new StringBuilder();
- List<string> keys = new List<string>();
- ConcurrentDictionary<string, Task> Threads = new ConcurrentDictionary<string, Task>();
- ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSources = new ConcurrentDictionary<string, CancellationTokenSource>();
-
- /// <summary>
- /// 停止指定任务
- /// </summary>
- /// <param name="key">任务名</param>
- /// <param name="ExitCallback">任务结束的回调</param>
- public void StopTask(string key, Action ExitCallback = null)
- {
- if (CancellationTokenSources.ContainsKey(guid + key))
- {
- CancellationTokenSources[guid + key]?.Cancel();
- ActionManage.GetInstance.Register(ExitCallback, guid + key);
- }
- else
- {
- if (ExitCallback != null) ExitCallback();
- }
- }
-
- /// <summary>
- /// 长任务,带 while true 的循环
- /// </summary>
- /// <param name="action"></param>
- /// <param name="key"></param>
- public void StartLong(Action action, string key, bool IsRestart = false, Action RunComplete = null)
- {
- if (!Threads.ContainsKey(guid + key))
- {
- CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
- bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
- {
- Thread.CurrentThread.Name = key;
- MessageLog.GetInstance.Show($"启动线程 【{key}】");
- ReStart:
- try
- {
- while (!CancellationTokenSources[guid + key].IsCancellationRequested)
- {
- if (action != null) action();
- }
- }
- catch (Exception ex)
- {
- MessageLog.GetInstance.ShowEx(ex.ToString());
- MessageLog.GetInstance.ShowEx(ex.Message);
- if (IsRestart)
- {
- Thread.Sleep(2000);
- MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已重启");
- goto ReStart;
- }
- else
- {
- CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource temp);
- Threads.TryRemove(guid + key, out Task temp1);
- MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常,已退出");
- }
- }
- }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
- {
- ThreadStatus(t, o.ToString());
- if (RunComplete != null) RunComplete();
- }), guid + key));
- }
- else MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
-
- }
-
-
- /// <summary>
- /// 不带 while true 的循环任务
- /// </summary>
- /// <param name="action"></param>
- /// <param name="key"></param>
- public void Start(Action action, string key, bool isRestart = false)
- {
- if (!Threads.ContainsKey(guid + key))
- {
- CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
- bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
- {
- Thread.CurrentThread.Name = key;
- MessageLog.GetInstance.Show($"启动线程 【{key}】");
- try
- {
- if (action != null) action();
- }
- catch (Exception ex)
- {
- MessageLog.GetInstance.ShowEx(ex.ToString());
- if (isRestart)
- {
- MessageLog.GetInstance.Show($"线程 【{key}】正在重启");
- CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource item1);
- Threads.TryRemove(guid + key, out Task item2);
- Start(action, key, isRestart);
- }
- else
- {
- MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常");
- }
- }
- }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
- {
- ThreadStatus(t, o.ToString());
- }), guid + key));
- }
- else MessageLog.GetInstance.Show($"【{key}】任务已存在,请检查 TaskName");
- }
-
- private void ThreadStatus(Task task, string key)
- {
- bool IsRemove = false;
- string name = key.Substring(key.LastIndexOf('-') + 1);
- switch (task.Status)
- {
- case TaskStatus.RanToCompletion:
- MessageLog.GetInstance.Show($"线程【{name}】执行完成");
- IsRemove = true;
- break;
- case TaskStatus.Faulted:
- MessageLog.GetInstance.Show($"线程【{name}】执行异常,{task.Exception}");
- IsRemove = true;
- break;
- case TaskStatus.Canceled:
- MessageLog.GetInstance.Show($"线程【{name}】已取消");
- IsRemove = true;
- break;
- default:
- break;
- }
-
- if (IsRemove)
- {
- if (Threads.ContainsKey(key))
- Threads.TryRemove(key, out Task t);
- //Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName));
-
-
- if (CancellationTokenSources.ContainsKey(key))
- CancellationTokenSources.TryRemove(key, out CancellationTokenSource cts);
- //CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName));
- //keys.Remove(key);
- //if (keys != null && keys.Count == 0) ActionManage.GetInstance.Send(callbackKey.ToString());
- ActionManage.GetInstance.Send(key);
- }
- }
-
- /// <summary>
- /// 释放所有线程资源
- /// </summary>
- public void Dispose()
- {
- for (int i = 0; i < CancellationTokenSources.Count; i++)
- {
- CancellationTokenSources.ElementAt(i).Value.Cancel();
- }
- }
-
- /// <summary>
- /// 判断指定线程是否完成
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public bool IsComplete(string key)
- {
- if (Threads.ContainsKey(guid + key)) return Threads[guid + key].IsCompleted;
- return false;
- }
-
- /// <summary>
- /// 根据key获取取消状态,为start()开启的task在外部停止使用。
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public bool IsCanncel(string key)
- {
- if (CancellationTokenSources.ContainsKey(guid + key)) return CancellationTokenSources[guid + key].IsCancellationRequested;
- return false;
- }
-
- public bool IsContainsKey(string key)
- {
- return Threads.ContainsKey(guid + key);
- }
- }
- }
|