你的位置:首页 > ASP.net教程

[ASP.net教程]c# 多线程系列二 自定义线程执行器


看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~!

那么今天我来讲讲,怎么样构建通用的自定义线程概念!

线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路处理一类任务,显然不满足我们的实际场景的需求,那么怎么才能创建灵活的线程执行器呢!

首先我们来创建一个任务构造器!

 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   }

 

运行结果图

 

看到这里是不是很清楚明了呢?这样我们在处理日常任务的时候,不同类型的逻辑或者任务类型,是不是都可以放到一个线程执行呢?

 

请大家期待我的下一篇文章,为大家讲解,定时器线程执行器,