c# 多线程系列二 自定义线程执行器
看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~!
那么今天我来讲讲,怎么样构建通用的自定义线程概念!
线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路处理一类任务,显然不满足我们的实际场景的需求,那么怎么才能创建灵活的线程执行器呢!
首先我们来创建一个任务构造器!
/// <summary> /// 线程模型执行任务 基类 /// </summary> public abstract class BaseTask { /// <summary> /// 任务ID /// </summary> public long TID { get; set; } /// <summary> /// 任务名称 /// </summary> public string TName { get; set; } /// <summary> /// 线程模型任务 /// </summary> public abstract void Run(); public override string ToString() { return "Task<" + this.TName + "(" + TID + ")>"; } }
看到这里,可能不会明白,这么写法的意义在哪里呢?
那么我们再来自定义线程的执行器
/// <summary> /// 定义自定义线程模型 /// </summary> public abstract class BaseThread<T> where T : BaseTask { //执行线程 Thread _Thread; //通知一个或多个正在等待的线程已发生事件 ManualResetEvent mre = new ManualResetEvent(false); //线程安全的队列 System.Collections.Concurrent.ConcurrentQueue<T> cqueue = new System.Collections.Concurrent.ConcurrentQueue<T>(); /// <summary> /// 自定义线程ID; /// </summary> public long TID { get; set; } public static bool IsRuning = true; /// <summary> /// 初始化 /// </summary> /// <param name="tName">线程的名称</param> public BaseThread(string tName) { _Thread = new Thread(Runing); _Thread.Name = tName; _Thread.Start(); } //模拟新增任务 public void AddTask(T task) { //添加任务到队列 cqueue.Enqueue(task); //唤醒所有相关的挂起线程 mre.Set(); } void Runing() { //主循环 服务器运行标识 while (IsRuning) { //如果是空则继续等待 服务器运行标识 while (cqueue.IsEmpty && IsRuning) { //重置线程暂停状态 mre.Reset(); //这个操作是以便服务器需要停止操作, //如果停止调用线程的Thread.Abort()是会导致处理队列任务丢失 mre.WaitOne(); #if DEBUG //为了方便测试信息打印的暂停信息 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Status Sleep"); #endif } T t; //取出队列任务 if (cqueue.TryDequeue(out t)) { Runing(t); } } } /// <summary> /// 设置运行方法为虚方法,方便子函数覆盖 /// </summary> protected virtual void Runing(T run) { try { //执行任务 run.Run(); //打印任务信息 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString()); } catch (Exception ex) { //打印任务信息 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString() + " Exception:" + ex); } } }
看到这里是不是比较清楚了?这样我们定义的线程是不是能完成多不同类型的任务呢?
是不是可以做到一个线程执行和处理不同类型的任务呢?
接下来我们创建类型的实现类
任务实现类1
/// <summary> /// 测试任务 /// </summary> public class TestTask : BaseTask { public override void Run() { Console.WriteLine("我只是用来测试的"); } }
任务实现类2
public class TestTask1 : BaseTask { /// <summary> /// 执行任务 /// </summary> public Action Test { get; set; } public override void Run() { if (Test != null) { Test(); } Console.WriteLine("我只是用来测试的"); } }
线程的实现类
/// <summary> /// 测试线程 /// </summary> public class TestThread : BaseThread<BaseTask> { public TestThread() : base("TestThread") { } }
接下来我们看看测试效果
class Program { static void Main(string[] args) { TestThread tt = new TestThread(); tt.AddTask(, TName = "测试1" }); tt.AddTask(, TName = "测试2" }); tt.AddTask(, TName = ); }) }); tt.AddTask(, TName = "测试4" }); Console.ReadLine(); } }
运行结果图
看到这里是不是很清楚明了呢?这样我们在处理日常任务的时候,不同类型的逻辑或者任务类型,是不是都可以放到一个线程执行呢?
请大家期待我的下一篇文章,为大家讲解,定时器线程执行器,
c# 多线程系列二 自定义线程执行器的更多相关文章
- (Java多线程系列二)线程间同步
Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...
- java多线程系列(二)
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- java多线程系列(二)---对象变量并发访问
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- java多线程编程(二创建线程)
1.概念 因为java是完全面向对象的,所以在java中,我们说的线程,就是Thread类的一个实例对象.所以,一个线程就是一个对象,它有自己字段和方法. 2.创建线程 创建线程有 ...
- Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)
一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...
- java多线程(四)-自定义线程池
当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的 ...
- java多线程(二)-线程的生命周期及线程间通信
一.摘要 当我们将线程创建并start时候,它不会一直占据着cpu执行,而是多个线程间会去执行着这个cpu,此时这些线程就会在多个状态之间进行着切换. 在线程的生命周期中,它会有5种状态,分别为 ...
- java多线程系列六、线程池
一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池. 2. 使用线程池的好处 a) 降低资源的消耗.使用线程池不用频繁的创建线程和销毁线程 b) 提高响应速度,任 ...
- Java 多线程(二)—— 线程的同步
上文创建多线程买票的例子中注释会出现错票.重票的问题,本文来讲讲如何解决此问题.本文例子:利用多线程模拟 3 个窗口卖票 实现Runnable接口 public class TestThread2 ...
随机推荐
- python 调用nmap
1.系统中需要安装nmap 2.系统中安装pip 2.安装python调用nmap的lib包 命令为:pip install python-nmap 以下是在centos系统下安装成功后的截图 在命令 ...
- 使用开源库MAGICODES.WECHAT.SDK进行微信公众号支付开发
概要 博客使用Word发博,发布后,排版会出现很多问题,敬请谅解.可加群获取原始文档. 本篇主要讲解微信支付的开发流程,相关业务基于MAGICODES.WECHAT.SDK实现.通过本篇教程,您可以很 ...
- 使用call来实现继承
function Class1(arg1,arg2) { this.name = arg1; this.pass = arg2; this.showSub = function() { return ...
- Linux计划任务crontab运行脚本不正确的问题
问题的由来 写好的程序希望在崩溃之后能够自启动,于是利用linux的crontab功能,添加一个计划任务,每分钟执行一个脚本查看需要监控的进程是否还在,如果不在则启动之,否则不做任何事情.这么一个简单 ...
- 为自己搭建一个鹊桥 -- Native Page与Web View之间的JSBridge实现方式
说起JSBridge,大家最熟悉的应该就是微信的WeixinJSBridge,通过它各个公众页面可以调用后台方法和微信进行交互,为用户提供相关功能.我们就来说说UWP下怎么样实现我们自己的JSBrid ...
- [.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)
[.net 面向对象编程基础] (10) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态 ...
- 一天一小段js代码(no.3)
//遍历属性,返回名值对 function outputAttributes(element){ var pairs = new Array(), attrName, attrValue, i, le ...
- [体感游戏] 1、MPU6050数据采集传输与可视化
最近在研究体感游戏,到目前为止实现了基于51单片机的MPU6050数据采集.利用蓝牙模块将数据传输到上位机,并利用C#自制串口数据高速采集软件,并且将数据通过自制的折线图绘制模块可视化地展示出来等功能 ...
- ReactMix框架,让你实现一套js代码,基于ReactNative在H5,App都能完美跑起来,Write Once,Run Anywhere
ReactNative框架推出已经有一段时间了,相信很多小伙伴都在尝试实现Write Once, Run Anywhere的梦想,比如淘宝的ReactWeb等等,但是这些框架都局限于因为ReactNa ...
- iOS 向模拟器里添加照片
iOS 向模拟器里添加照片 模拟器里Photos最开始时是没有照片的,有时我们做Demo时需要Photos里面的照片做测试,这时就需要把Mac上的照片导入到模拟器里.步骤如下: 1,打开模拟器 2,选 ...