C# 线程--第四线程实例
概述
在前面几节中和大家分享了线程的一些基础使用方法,本章结合之前的分享来编写一些日常开发中应用实例,和编写多线程时一些注意点。如大家有好的实例也欢迎分享..
应用实例
应用:定时任务程序
场景:系统中常常会有一些需要定时去循环执行的存储过程或方法等,这时就出现了定时任务小程序。
模型:查询需定时执行的计划任务-->插入线程池-->执行任务
static void MainMethod()
{
Thread thead; thead = new Thread(QueryTask);
thead.IsBackground = true;
thead.Start(); Console.Read();
} /// <summary>
/// 查询计划任务
/// </summary>
static void QueryTask()
{
TaskModel todo_taskModel;
while (true)
{
int count = new Random().Next(, ); //模拟产生任务记录数
for (int i = ; i < count; i++)
{
todo_taskModel = new TaskModel() { TaskID = i, ITime = DateTime.Now };
ThreadPool.QueueUserWorkItem(InvokeThreadMethod, todo_taskModel);
} Thread.Sleep(); //30s循环一次
}
} /// <summary>
/// 完成计划任务
/// </summary>
/// <param name="taskModel"></param>
static void InvokeThreadMethod(object taskModel)
{
TaskModel model = (TaskModel)taskModel; Console.WriteLine("执行任务ID:{0}......执行完成.{1}", model.TaskID, model.ITime);
} /// <summary>
/// 任务实体
/// </summary>
class TaskModel
{
public int TaskID { get; set; }
public DateTime ITime { get; set; }
}
1.查询计划任务时只管有任务就推给线程池,不等待线程池中任务是否完成.(避免有些计划任务耗时比较长,阻塞后面定时任务执行时间)每隔30秒循环一次计划任务.
2.每条计划任务完成后打印相应信息.(也可记录日志)
3.如果查询计划任务记录数较多,可调整相应的循环时间间隔。避免任务插入线程池时间过长阻塞后面定时任务执行时间。
应用:数据推送程序
场景:在我们日常系统中会存在很多接口数据需要实时推送给第三方平台(如:会员信息发生变化推送给微信平台..)。这时我们就需写一些数据推送程序。
模型:检索任务-->插入线程池-->等待线程池任务完成-->提示任务完成
static void MainMethodB()
{
Thread thread = new Thread(QueryTaskB);
thread.IsBackground = true;
thread.Start(); Console.Read();
} static void QueryTaskB()
{
MutipleThreadResetEvent countdown;
TaskModeB model;
while (true)
{
int RandomNumber = new Random().Next(, );
countdown = new MutipleThreadResetEvent(RandomNumber);
for (int i = ; i < RandomNumber; i++)
{
model = new TaskModeB() { TaskId = i, ITime = DateTime.Now, manualResetEvent = countdown };
ThreadPool.QueueUserWorkItem(InvokeThreadMethodB, model);
} //等待所有线程执行完毕
countdown.WaitAll();
Console.WriteLine("线程池任务已完成.完成时间:{0}", DateTime.Now);
Thread.Sleep();
}
} static void InvokeThreadMethodB(object obj)
{
TaskModeB model = (TaskModeB)obj;
Thread.Sleep();
Console.WriteLine("执行任务ID:{0},执行时间:{1},完成时间:{2}", model.TaskId, model.ITime, DateTime.Now); //发送信号量 本线程执行完毕
model.manualResetEvent.SetOne();
} class TaskModeB
{
public int TaskId { set; get; }
public DateTime ITime { set; get; }
public MutipleThreadResetEvent manualResetEvent { set; get; }
} /// <summary>
/// 解决问题:WaitHandle.WaitAll(evetlist)方法最大只能等待64个ManualResetEvent事件
/// </summary>
public class MutipleThreadResetEvent
{
private readonly ManualResetEvent done;
private readonly int total;
private long current; /// <summary>
/// 构造函数
/// </summary>
/// <param name="total">需要等待执行的线程总数</param>
public MutipleThreadResetEvent(int total)
{
this.total = total;
current = total;
done = new ManualResetEvent(false);
} /// <summary>
/// 唤醒一个等待的线程
/// </summary>
public void SetOne()
{
// Interlocked 原子操作类 ,此处将计数器减1
if (Interlocked.Decrement(ref current) == )
{
//当所以等待线程执行完毕时,唤醒等待的线程
done.Set();
}
} /// <summary>
/// 等待所以线程执行完毕
/// </summary>
public void WaitAll()
{
done.WaitOne();
} /// <summary>
/// 释放对象占用的空间
/// </summary>
public void Dispose()
{
((IDisposable)done).Dispose();
}
}
QueryTaskB()在检索任务记录数后会记录任务条数,并实例化对应的ManualResetEvent数组,做为参数传给线程池中线程任务。
最后等待线程池中所有任务执行完成。后续可根据实际需要编写各自业务逻辑。
两个实例的不同点:是否等待线程池中的所有任务完成。
实例1中定时任务对执行的时间要求比较高,到了某个时间点必须执行某个任务。所以不能等待线程池中的任务完成。
缺点:有任务就插入线程池,有些任务可能会执行很久,线程池每隔30秒循环一次,最后会导致线程池中有存在很多耗时很长的任务在线程池中未执行完。当线程池中线程数达到1023(线程池默认最大线程数)后线程池就不会在创建新的线程数去完成新的任务,只能等待当前线程池中线程数得到释放。
实例2中数据推送程序对推送的时间要求相对1中要低一点。接口表中只要检索到数据就推送给第三方平台。一般每次传输数据量不是很多,但很频繁。
缺点:当推送数据量大时,执行任务时间可能会较长。主线程会等待线程池中的所有任务完成。所有每次循环检索任务的时间间隔可能会出现30S+NS现象。
C# 线程--第四线程实例的更多相关文章
- Java多线程(四) 线程池
一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...
- 第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案
一. 背景 揭秘: 在前面的章节介绍过,Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然也可以基本业务需要的多线程场景,但它们在多个线程的等待处理方面 ...
- {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器
Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...
- Java多线程(四) —— 线程并发库之Atomic
一.从原子操作开始 从相对简单的Atomic入手(java.util.concurrent是基于Queue的并发包,而Queue,很多情况下使用到了Atomic操作,因此首先从这里开始). 很多情况下 ...
- C#中的线程(四)高级话题
C#中的线程(四)高级话题 Keywords:C# 线程Source:http://www.albahari.com/threading/Author: Joe AlbahariTranslato ...
- Java创建线程的四种方式
Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...
- java多线程(一)创建线程的四种方式
1. 什么是并发与并行 要想学习多线程,必须先理解什么是并发与并行 并行:指两个或多个事件在同一时刻发生(同时发生). 并发:指两个或多个事件在同一个时间段内发生. 2. 什么是进程.线程 进 ...
- Java并发编程 (四) 线程安全性
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.线程安全性-原子性-atomic-1 1.线程安全性 定义: 当某个线程访问某个类时,不管运行时环境 ...
- java创建线程的四种方法
第一种: 通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runna ...
随机推荐
- PowerShell管理IIS(新建站点、应用程序池、应用程序、虚拟目录等)
#导入IIS管理模块 Import-Module WebAdministration #新建应用程序池 api.dd.com New-Item iis:\AppPools\api.dd.com Set ...
- Oracle_11g_R2安装详解_for_Windows_7
Oracle 11g R2安装全攻略 - For Windows 7 图文教程 1.下载Oracle 11g R2的Windows版本,官方下载地址如下: http://download.oracle ...
- ssh 设置免password登录
如果: 实现->操作机A机 要以用户"user1"身份.免password登录B机和C机? B机和C机 建立用户 user1 而且能够ssh 登录. A机设置: 1.安装ss ...
- TcxDBLookupCombobox 级联时第二级不显示正确内容的处理方法
在使用两个级联的 TcxDBLookupCombobox 时,会出现这种情况:当第一级的内容变更后,第二级的控件在界面上显示的文本不变化,即使数据集已经通过 Properites.OnChange 事 ...
- 【转】shell脚本处理字符串的常用方法
转自:http://blog.csdn.net/linfeng999/article/details/6661233 1. 构造字符串 直接构造 STR_ZERO=hello #shell中等号左右的 ...
- 下载discuz 6 论坛的附件
前段时间我下了个python脚本把emsky的附件全部下载了,之前是因为偶然发现emsky附件不登陆也能访问,直接访问一个url就行了. 后来发现大部分discuz6的论坛都有这个bug,我想是因为d ...
- BZOJ 2456: mode 水题
2456: mode Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php? ...
- 第一周:读取XML深度数据并将其重建为三维点云
本周主要任务:学习PCL点云库,掌握利用PCL对点云处理的方法 任务时间:2014年9月1日-2014年9月7日 任务完成情况:完成了读取单幅xml深度数据,并重建三维点云并显示 任务涉及基本方法: ...
- SlideLayout
https://github.com/rey5137/SlideLayout
- iOS开发——实用篇Swift篇&保存图片到相册
保存图片到相册 最近在深入的学习关于swift相关技术,虽然海做不出什么好的东西,但是感觉收获不少,相信总有一样能用到,所以就总结了一下,希望大家喜欢! 1.OC中的写法 在OC中,我们需要保存图片到 ...