解决一个C#中定时任务被阻塞问题
解决一个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#中定时任务被阻塞问题的更多相关文章
- 记录解决一个项目中遇到的maven打包问题
拿到同时给的代码,进行打jar包,这个jar包依赖一个第三方的jar包,一开始用IDEA打出来的包,没有把依赖的包打进去,后来查了相关的资料, 发现需要在maven的pom中添加相关的maven插件, ...
- 位运算解决“一个数组中,只有一个数字出现n次,其他数字出现k次”问题
转自:https://blog.csdn.net/monster_girl/article/details/52928864 在学习完位操作后,经常会遇到一类关于查找缺失整数的问题. 第一类是给你一个 ...
- 解决一个Ubuntu中编译NEON优化的OpenCV的错误
在Ubuntu 16中编译开启NEON优化的Opencv时,遇到libpng编译是使用汇编代码的错误,完整错误见文章末尾.通过查询发现解决方案是安装跨平台编译器,安装代码如下: sudo apt-ge ...
- WebApi一个控制器中定义多个Get方法。
问题:怎样解决一个ApiController中定义多个Get方法或者Post方法? 答:要想实现一个ApiController中定义多个Get方法或者Post方法,则需要在WebApiConfig类中 ...
- 另一个 OleDbParameterCollection 中已包含 OleDbParameter 错误分析及解决办法
程序非常简单,就是从一个表中取出一个符合要求的数据,如果取到,就把该数据对应的计数加1.也就是执行不同的两个SQL语句操作同一个表,并且这两个SQL的参数是一样的.在一个函数里完成这个调用.执行第二个 ...
- js中关于一个数组中最大、最小值以及它们的下标的输出的一种解决办法
今天在学习js中的数组时,遇到的输出一个数组中最大.最小值以及它们的下表,以下是自己的解决方法! <script type="text/javascript"> var ...
- 解决tomcat下面部署多个项目log4j的日志输出会集中输出到一个项目中的问题
在一次项目上线后,发现了一个奇怪的问题,经过对源码的阅读调试终于解决,具体经过是这样的: 问题描述:tomcat7下面部署多个项目,log4j的日志输出会集中输出到一个项目中,就算配置了日志文件的绝对 ...
- 解决QML开发中ComboBox中一个已选择项没有清除的问题
解决QML开发中ComboBox中一个已选择项没有清除的问题 近期使用QML开发一个项目.须要使用ComboBox进行显示.当进行一个操作时,须要向ComboBox加入一个元素,当进行另外一个操作时. ...
- 解决:一个项目中写多个包含main函数的源文件并分别调试运行
自己在学c++的时候,一个项目中的多个cpp文件默认不允许多个main函数的出现,但是通过选项操作能够指定单个cpp文件进行运行,如下: 1.此时我就想运行第二个cpp文件,我们只需要把其他的两个右键 ...
随机推荐
- 使用亚马逊服务器报错:Signature not yet current: 20190726T070253Z is still later than 20190726T070246Z (20190726T065746Z + 15 min.)时间不同步的解决办法
1.首先获取亚马逊的时间: $ curl http://s3.amazonaws.com -v 2.更改当前服务器时间,使之与亚马逊时间同步 $ date -s 'xxxx-xx-xx xx:xx:x ...
- [转载]PHP命名规则
PHP命名规则 引用地址:http://www.cnblogs.com/pengxl/p/3571157.html 就一般约定而言,类.函数和变量的名字应该是能够让代码阅读者能够容易地知道这些代码的作 ...
- P5056-[模板]插头dp
正题 题目链接:https://www.luogu.com.cn/problem/P5056 题目大意 \(n*m\)的网格,求有多少条回路可以铺满整个棋盘. 解题思路 插头\(dp\)的,写法是按照 ...
- YbtOJ#573-后缀表达【二分图匹配】
正题 题目链接:https://www.ybtoj.com.cn/contest/115/problem/2 题目大意 给出一个包含字母变量和若干种同级操作符的后缀表达式.求一个等价的表达式满足该表达 ...
- mybatis: No enum constant org.apache.ibatis.type.JdbcType."VARCHAR"
mybatis 插入的时候一句sql报错如下. org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ib ...
- Xamarin Android使用自签名证书
背景 项目中后台web服务部署成https服务时,需要使用SSL证书,如果我们不使用公共的CA时,怎么办? 不仅如此,因为是小项目,App应用主要是小范围使用,此时只有IP地址,根本没有域名,怎么办? ...
- Mysql explain中key_len的作用及计算规则
key_len表示索引使用的字节数,根据这个值可以判断索引的使用情况,特别是在组合索引的时候,判断该索引有多少部分被使用到非常重要. 在计算key_len时,下面是一些需要考虑的点: 索引字段的附加信 ...
- Windows10系统下Java JDK下载、安装与环境变量配置(全网最全步骤)
1.首先要明确: JDK.JRE.JVM的含义 2.下载目前最新的JDK:Java SE Development Kit 17,传送门::https://www.oracle.com/java/tec ...
- Blazor Webassembly多标签页开发
最近准备用Blazor Webassembly做后台开发要用到多标签页,找了半天发现绝大多数都是Blazor Server的多标签没有Webassembly.没办法只能自己想办法造轮子了. 查了许多资 ...
- 简单几步零成本使用Vercel部署OneIndex 无需服务器搭建基于OneDrive的网盘
前提 你需要一个OneDrive账号,必须管理员开放API 需要已安装Node.js 拥有Github账号,没有就注册一个 魔法上网环境(看情况) 注册应用 登录https://portal.azur ...