解决一个C#中定时任务被阻塞问题

1.摘要

本文会介绍一个C#中最简单定时任务的使用方法,以及会遇到的定时任务被阻塞现象,从笔者理解的角度分析原因。以及提供解决方案。

2.C#中定时任务的最简方法

  protected internal void PollClient()
{
int i=0;
Timer t = new Timer(p => {
i++;
if (deviceContextList.Count > 0)
{
var deviceContext=GetDeviceContext("123456789");
SendMessage(messageList[i%7],deviceContext.tcpSession.writerContext);
logger.Info("客户端数量:"+ deviceContextList.Count);
}
else
{
logger.Info("客户端数量为0");
Console.WriteLine("客户端数量为0");
}
}, null, 0, 1000) ;
}

上面的timer方法提供于微软System.Threading命名空间。System.Threading.Timer 是由线程池调用的。所有的Timer对象只使用了一个线程来管理。这个线程知道下一个回调对象在什么时候到期。下一个回调对象到期时,线程就会唤醒,在内部调用ThreadPool 的 QueueUserWorkItem,将一个工作项添加到线程池队列中,使你的回调方法得到调用。此方法有多个重载,具体读者可以自行去看。

Timer(TimerCallback callback, object state, int dueTime, int period)

第一个参数callback是回调方法,第二个参数state可以传参给回调方法的参数,第三个参数dueTime是第一次执行回调函数的延时时间,单位毫秒,第四个参数period是调用回调函数的时间间隔。使用起来是不是特别方便,把你需要执行的定时任务放在回调方法中,可独立写成方法,也可像上面一样写成匿名方法的形式。

3.定时任务阻塞现象

当上述任务被执行了几千次以后,定时任务会阻塞,不再执行,也不再打印日志。并且上面的写法有缺陷,。如果回调方法的执行时间很长,计时器可能(在上个回调还没有完成的时候)再次触发。这可能造成多个线程池线程同时执行你的回调方法。并且线程切换也会造成诸多损耗时间。

4.阻塞现象原因分析

上面的方法中使用局部变量来创建指向一个线程定时器。因为局部变量会被GC回收,导致定时器失效。

具体改进如下:

static int i=0;
static Timer _timer = null;
protected void PollClient()
{
_timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite) ;
}
private void TimerCallback(object state)
{
try
{
i++; if (deviceContextList.Count > 0)
{
var deviceContext = GetDeviceContext("123456789");
SendMessage(messageList[i % 7], deviceContext.tcpSession.writerContext);
logger.Info("客户端数量:" + deviceContextList.Count + "循环次数:" + i); }
else
{
logger.Info("客户端数量为0" + "循环次数:" + i);
Console.WriteLine("客户端数量为0" + "循环次数:" + i);
}
}
catch (Exception e)
{
logger.Error("定时测试下发报文异常:" + e);
}
finally
{
_timer.Change( 1000, Timeout.Infinite);
}
}

将定时器与计数变量设置为static是为了定时器不被GC回收。定时任务执行完成之后再设置下次调用时间间隔是为了该任务不过多占用线程池中的线程,节省线程切换时间等。

5.问题解决

可以看到任务已经被执行了86665次,优化后不再被GC回收。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/JerryMouseLi/p/15543495.html

解决一个C#中定时任务被阻塞问题的更多相关文章

  1. 记录解决一个项目中遇到的maven打包问题

    拿到同时给的代码,进行打jar包,这个jar包依赖一个第三方的jar包,一开始用IDEA打出来的包,没有把依赖的包打进去,后来查了相关的资料, 发现需要在maven的pom中添加相关的maven插件, ...

  2. 位运算解决“一个数组中,只有一个数字出现n次,其他数字出现k次”问题

    转自:https://blog.csdn.net/monster_girl/article/details/52928864 在学习完位操作后,经常会遇到一类关于查找缺失整数的问题. 第一类是给你一个 ...

  3. 解决一个Ubuntu中编译NEON优化的OpenCV的错误

    在Ubuntu 16中编译开启NEON优化的Opencv时,遇到libpng编译是使用汇编代码的错误,完整错误见文章末尾.通过查询发现解决方案是安装跨平台编译器,安装代码如下: sudo apt-ge ...

  4. WebApi一个控制器中定义多个Get方法。

    问题:怎样解决一个ApiController中定义多个Get方法或者Post方法? 答:要想实现一个ApiController中定义多个Get方法或者Post方法,则需要在WebApiConfig类中 ...

  5. 另一个 OleDbParameterCollection 中已包含 OleDbParameter 错误分析及解决办法

    程序非常简单,就是从一个表中取出一个符合要求的数据,如果取到,就把该数据对应的计数加1.也就是执行不同的两个SQL语句操作同一个表,并且这两个SQL的参数是一样的.在一个函数里完成这个调用.执行第二个 ...

  6. js中关于一个数组中最大、最小值以及它们的下标的输出的一种解决办法

    今天在学习js中的数组时,遇到的输出一个数组中最大.最小值以及它们的下表,以下是自己的解决方法! <script type="text/javascript"> var ...

  7. 解决tomcat下面部署多个项目log4j的日志输出会集中输出到一个项目中的问题

    在一次项目上线后,发现了一个奇怪的问题,经过对源码的阅读调试终于解决,具体经过是这样的: 问题描述:tomcat7下面部署多个项目,log4j的日志输出会集中输出到一个项目中,就算配置了日志文件的绝对 ...

  8. 解决QML开发中ComboBox中一个已选择项没有清除的问题

    解决QML开发中ComboBox中一个已选择项没有清除的问题 近期使用QML开发一个项目.须要使用ComboBox进行显示.当进行一个操作时,须要向ComboBox加入一个元素,当进行另外一个操作时. ...

  9. 解决:一个项目中写多个包含main函数的源文件并分别调试运行

    自己在学c++的时候,一个项目中的多个cpp文件默认不允许多个main函数的出现,但是通过选项操作能够指定单个cpp文件进行运行,如下: 1.此时我就想运行第二个cpp文件,我们只需要把其他的两个右键 ...

随机推荐

  1. 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 | 百篇博客分析OpenHarmony源码 | v42.02

    百篇博客系列篇.本篇为: v42.xx 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪 ...

  2. 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 百篇博客分析OpenHarmony源码 | v31.02

    百篇博客系列篇.本篇为: v31.xx 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 51.c.h .o 本篇说清楚定时器的实现 读本篇之前建议先读鸿蒙内核源码分析(总目录)其余篇. 运 ...

  3. Winform 控件命名规范

    前言 最近 Winform 项目做得比较多,控件命名规范上常用的能记住,但是有些总要查,写个记录吧.方便以后自己用,大家也可以参考. 标准控件 序号 控件类型简写 控件类型 1 btn Button ...

  4. 启用 Spring-Cloud-OpenFeign 配置可刷新,项目无法启动,我 TM 人傻了(上)

    本篇文章涉及底层设计以及原理,以及问题定位,比较深入,篇幅较长,所以拆分成上下两篇: 上:问题简单描述以及 Spring Cloud RefreshScope 的原理 下:当前 spring-clou ...

  5. xshell 连接virtualbox nat模式的虚拟主机的方式

    因为垃圾CSDN抽风无法收藏文章 所以保存了一片文章 https://blog.csdn.net/Trista_WU/article/details/79873310?utm_medium=distr ...

  6. 实验1:SDN拓扑实践

    作业链接:实验1:SDN拓扑实践 一.实验目的 能够使用源码安装Mininet: 能够使用Mininet的可视化工具生成拓扑: 能够使用Mininet的命令行生成特定拓扑: 能够使用Mininet交互 ...

  7. 5.深入TiDB:Insert 语句

    本文基于 TiDB release-5.1进行分析,需要用到 Go 1.16以后的版本 我的博客地址:https://www.luozhiyun.com/archives/605 这篇文章我们看一下 ...

  8. WebMagic 爬虫技术

    WebMagic WebMagic 介绍 WebMagic基础架构 Webmagic 的结构分为 Downloader.PageProcessor.Scheduler.Pipeline四大组件,并由 ...

  9. WPF进阶技巧和实战08-依赖属性与绑定02

    将元素绑定在一起 数据绑定最简单的形式是:源对象是WPF元素而且源属性是依赖项属性.依赖项属性内置了更改通知支持,当源对象中改变依赖项属性时,会立即更新目标对象的绑定属性. 元素绑定到元素也是经常使用 ...

  10. vite首次启动加载慢

    背景 随着vue3的到来,vite开始被各大vue3组件库使用,公司开始一个新项目,准备尝试用vite试一波. 问题发现 当把公司新项目移植到vite后,启动非常快,但发现页渲染时间慢了很多 可以看到 ...