看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~!
那么今天我来讲讲,怎么样构建通用的自定义线程概念!
线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路处理一类任务,显然不满足我们的实际场景的需求,那么怎么才能创建灵活的线程执行器呢!
首先我们来创建一个任务构造器!
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 DEBUG 54 //为了方便测试信息打印的暂停信息 55 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Status Sleep"); 56 #endif 57 } 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 try 73 { 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 }
运行结果图
看到这里是不是很清楚明了呢?这样我们在处理日常任务的时候,不同类型的逻辑或者任务类型,是不是都可以放到一个线程执行呢?
请大家期待我的下一篇文章,为大家讲解,定时器线程执行器,