看了第一篇文章,多線程系列,看到了在線程執行任務隊列有了一定的了解~!
那么今天我來講講,怎么樣構建通用的自定義線程概念!
線程執行任務,肯定要有目標,但是如果寫死了,那么一個線程處理執行職能按照思路處理一類任務,顯然不滿足我們的實際場景的需求,那么怎么才能創建靈活的線程執行器呢!
首先我們來創建一個任務構造器!
1 /// <summary> 2 /// 線程模型執行任務 基類 3 /// </summary> 4 public abstract class BaseTask 5 { 6 7 /// <summary> 8 /// 任務ID 9 /// </summary>10 public long TID { get; set; }11 12 /// <summary>13 /// 任務名稱14 /// </summary>15 public string TName { get; set; }16 17 /// <summary>18 /// 線程模型任務19 /// </summary>20 public abstract void Run();21 22 public override string ToString()23 {24 return "Task<" + this.TName + "(" + TID + ")>";25 }26 }
看到這里,可能不會明白,這么寫法的意義在哪里呢?
那么我們再來自定義線程的執行器
1 /// <summary> 2 /// 定義自定義線程模型 3 /// </summary> 4 public abstract class BaseThread<T> where T : BaseTask 5 { 6 //執行線程 7 Thread _Thread; 8 //通知一個或多個正在等待的線程已發生事件 9 ManualResetEvent mre = new ManualResetEvent(false);10 //線程安全的隊列11 System.Collections.Concurrent.ConcurrentQueue<T> cqueue = new System.Collections.Concurrent.ConcurrentQueue<T>();12 13 /// <summary>14 /// 自定義線程ID;15 /// </summary>16 public long TID { get; set; }17 18 public static bool IsRuning = true;19 20 /// <summary>21 /// 初始化22 /// </summary>23 /// <param name="tName">線程的名稱</param>24 public BaseThread(string tName)25 {26 _Thread = new Thread(Runing);27 _Thread.Name = tName;28 _Thread.Start();29 }30 31 //模擬新增任務32 public void AddTask(T task)33 {34 //添加任務到隊列35 cqueue.Enqueue(task);36 //喚醒所有相關的掛起線程37 mre.Set();38 }39 40 void Runing()41 {42 //主循環 服務器運行標識43 while (IsRuning)44 {45 //如果是空則繼續等待 服務器運行標識46 while (cqueue.IsEmpty && IsRuning)47 {48 //重置線程暫停狀態49 mre.Reset();50 //這個操作是以便服務器需要停止操作,51 //如果停止調用線程的Thread.Abort()是會導致處理隊列任務丟失52 mre.WaitOne(2000);53 #if DEBUG54 //為了方便測試信息打印的暫停信息55 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Status Sleep");56 #endif57 }58 T t;59 //取出隊列任務60 if (cqueue.TryDequeue(out t))61 {62 Runing(t);63 }64 }65 }66 67 /// <summary>68 /// 設置運行方法為虛方法,方便子函數覆蓋69 /// </summary>70 PRotected virtual void Runing(T run)71 {72 try73 {74 //執行任務75 run.Run();76 //打印任務信息77 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString());78 }79 catch (Exception ex)80 {81 //打印任務信息82 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString() + " Exception:" + ex);83 }84 }85 }
看到這里是不是比較清楚了?這樣我們定義的線程是不是能完成多不同類型的任務呢?
是不是可以做到一個線程執行和處理不同類型的任務呢?
接下來我們創建類型的實現類
任務實現類1
1 /// <summary> 2 /// 測試任務 3 /// </summary> 4 public class TestTask : BaseTask 5 { 6 7 public override void Run() 8 { 9 Console.WriteLine("我只是用來測試的");10 }11 }
任務實現類2
1 public class TestTask1 : BaseTask 2 { 3 4 /// <summary> 5 /// 執行任務 6 /// </summary> 7 public Action Test { get; set; } 8 9 public override void Run()10 {11 if (Test != null)12 {13 Test();14 }15 Console.WriteLine("我只是用來測試的");16 }17 }
線程的實現類
1 /// <summary> 2 /// 測試線程 3 /// </summary> 4 public class TestThread : BaseThread<BaseTask> 5 { 6 public TestThread() 7 : base("TestThread") 8 { 9 10 }11 }
接下來我們看看測試效果
1 class Program 2 { 3 4 static void Main(string[] args) 5 { 6 TestThread tt = new TestThread(); 7 tt.AddTask(new TestTask() { TID = 1, TName = "測試1" }); 8 tt.AddTask(new TestTask1() { TID = 2, TName = "測試2" }); 9 tt.AddTask(new TestTask1() { TID = 2, TName = "測試3", Test = new Action(() => { Console.WriteLine("我要暫停3秒鐘"); Thread.Sleep(3000); }) });10 tt.AddTask(new TestTask() { TID = 3, TName = "測試4" });11 Console.ReadLine();12 }13 }
運行結果圖
看到這里是不是很清楚明了呢?這樣我們在處理日常任務的時候,不同類型的邏輯或者任務類型,是不是都可以放到一個線程執行呢?
請大家期待我的下一篇文章,為大家講解,定時器線程執行器,
新聞熱點
疑難解答