简述:

iis是一个很不错的服务器,有很多很好用的特性来支持网站运行,但有时候这些特性却会影响到我们开发者的一些操作。比如我们需要定时运行做一些操作,但由于iis的利用应用程序池来管理这种方式会让网站所在的进程在空闲(一段时间没人访问)时注销该线程,所以定时器是无法正常运行的。但利用asp.net的Cache机制是可以巧妙的实现能正常使用的定时器的。

运行效果:

请打开该链接

该网站定时每一个小时给该网页添加一条记录,而且估计我这个站点几百年都不会有一个人来访问一次的,大部分时间都是处于空闲状态的。

怎么使用:

网站添加WebTimerLib类库的引用

在合适的位置编写以下一行代码

 WebTimerLib.WebTimer timer = new WebTimerLib.WebTimer(new System.Threading.TimerCallback(TimeCallback), null, TimeSpan.FromSeconds(), TimeSpan.FromHours());

或者以下一行代码,推荐这行

WebTimerLib.WebTimer timer = new WebTimerLib.WebTimer(new System.Threading.TimerCallback(TimeCallback), null, TimeSpan.FromSeconds(), TimeSpan.FromSeconds(), "");

这行代码表示2秒后没一个小时运行一次TimeCallback这个方法

具体每个参数会在源码里有注释

源码:

源码是在.net 3.5的环境下开发的,估计.net2.0也是可以编译通过的。

类库下载地址

WebTimer类的代码:

 using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Web.Caching;
using System.Web; namespace WebTimerLib
{
/// <summary>
/// 可以正常在web使用的定时器
/// </summary>
public class WebTimer : IDisposable
{
/// <summary>
/// 初始化 Timer 类的新实例,使用 TimeSpan 值来度量时间间隔。
/// </summary>
/// <param name="callback">一个 TimerCallback 委托,表示要执行的方法。 </param>
/// <param name="state">一个包含回调方法要使用的信息的对象,或者为 空引用(在 Visual Basic 中为 Nothing)。 </param>
/// <param name="dueTime">TimeSpan,表示在 callback 参数调用它的方法之前延迟的时间量。指定 -1 毫秒以防止启动计时器。指定零 (0) 以立即启动计时器。 </param>
/// <param name="period">在调用 callback 所引用的方法之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
/// <param name="timerID">定时器标识符,不能重复</param>
/// <remarks>
/// 如果 dueTime 为零 (0),则立即调用 callback。如果 dueTime 是 -1 毫秒,则不会调用 callback;计时器将被禁用,但通过调用 Change 方法可以重新启用计时器。
/// 如果 period 为零 (0) 或 -1 毫秒,而且 dueTime 为正,则只会调用一次 callback;计时器的定期行为将被禁用,但通过使用 Change 方法可以重新启用该行为。
/// 为 callback 指定的方法应是可重入的,这是因为 ThreadPool 线程会调用该方法。该方法在以下两种情况下可以同时在两个线程池线程中执行:一是计时器间隔小于执行该方法所需的时间;二是所有线程池线程都在使用,并且多次对该方法进行排队。
/// </remarks>
public WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID)
{
_callback = callback;
_state = state;
_dueTime = dueTime;
_period = period;
_cacheID = timerID;
Run(dueTime);
} /// <summary>
/// 初始化 Timer 类的新实例,使用 TimeSpan 值来度量时间间隔, 建议使用WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID),避免造成更改定时器操作的时候,旧操作仍旧在运行
/// </summary>
/// <param name="callback">一个 TimerCallback 委托,表示要执行的方法。 </param>
/// <param name="state">一个包含回调方法要使用的信息的对象,或者为 空引用(在 Visual Basic 中为 Nothing)。 </param>
/// <param name="dueTime">TimeSpan,表示在 callback 参数调用它的方法之前延迟的时间量。指定 -1 毫秒以防止启动计时器。指定零 (0) 以立即启动计时器。 </param>
/// <param name="period">在调用 callback 所引用的方法之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
/// <param name="timerID">定时器标识符,重复的话会取消之前的任务</param>
/// <remarks>
/// 如果 dueTime 为零 (0),则立即调用 callback。如果 dueTime 是 -1 毫秒,则不会调用 callback;计时器将被禁用,但通过调用 Change 方法可以重新启用计时器。
/// 如果 period 为零 (0) 或 -1 毫秒,而且 dueTime 为正,则只会调用一次 callback;计时器的定期行为将被禁用,但通过使用 Change 方法可以重新启用该行为。
/// 为 callback 指定的方法应是可重入的,这是因为 ThreadPool 线程会调用该方法。该方法在以下两种情况下可以同时在两个线程池线程中执行:一是计时器间隔小于执行该方法所需的时间;二是所有线程池线程都在使用,并且多次对该方法进行排队。
/// </remarks>
public WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period)
{
_callback = callback;
_state = state;
_dueTime = dueTime;
_period = period;
Run(dueTime);
} private TimerCallback _callback;
private object _state;
private TimeSpan _dueTime;
private TimeSpan _period;
private bool _isDisposing = false;
private DateTime _NewDoCallbackTime; protected void Run(TimeSpan dueTime)
{
_NewDoCallbackTime = DateTime.Now.Add(dueTime);
HttpRuntime.Cache.Insert(CacheID, this, null, _NewDoCallbackTime, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(CacheItemRemovedCallback)); } private void CacheItemRemovedCallback(String key, Object value, CacheItemRemovedReason reason)
{
WebTimer timer = (WebTimer)value;
if (timer._isDisposing)
return;
if (reason == CacheItemRemovedReason.Expired)
{
if (timer._period < TimeSpan.FromSeconds())
_isDisposing = true;
timer._callback(_state);
timer.Run(timer._period);
}
else
{
timer.Run(_NewDoCallbackTime - DateTime.Now);
}
} /// <summary>
/// 更改计时器的启动时间和方法调用之间的时间间隔,使用 TimeSpan 值度量时间间隔。
/// </summary>
/// <param name="dueTime">一个 TimeSpan,表示在调用构造 Timer 时指定的回调方法之前的延迟时间量。指定负 -1 毫秒以防止计时器重新启动。指定零 (0) 以立即重新启动计时器。</param>
/// <param name="period">在构造 Timer 时指定的回调方法调用之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
/// <returns></returns>
public bool Change(TimeSpan dueTime, TimeSpan period)
{
this._dueTime = dueTime;
this._period = period;
try
{
HttpRuntime.Cache.Remove(CacheID);
this.Run(this._dueTime);
return true;
}
catch (Exception)
{
return false;
}
} private string _cacheID;
protected string CacheID
{
get
{
if (_cacheID == null) _cacheID = GetHashCode().ToString();
return _cacheID;
}
} #region IDisposable 成员 public void Dispose()
{
_isDisposing = true;
} #endregion }
}

补充:

对于我的书写能力我表示歉意,小时候语文没学好,文笔不好请见谅;能力水平有限,有什么说错的地方请多多指教;

关于转载,我不喜欢别人转载我的文章,觉得有价值的话就收藏到笔记之类软件,不会给搜索引擎收录的地方,我不太关注我的文章的版权问题,但我实在不喜欢自己在网上搜索资料的时候,搜到满满的一页是自己曾写过的一篇文章,实在恶心到我自己,我就注意到了一个情况,很多转载都不是为了学习的,而是一些公司不知道基于什么想法就转了过去,这样造成了搜索自己想要的资源会越来越难。但我发现如果是搜英文的资料的时候就很少有重复的,o(︶︿︶)o 唉,实在纠结啊!

补充(2013-7-28 7:08):

喉咙发炎,所以喝水太多,于是半夜起床,看了下定时器的运行情况,发现了奇怪的情况,如下图

有问题,怎么能安心入眠呢?于是一个经典的场面出现了,一个酷毙(苦逼)的程序猿在夜深人静的时候努力的敲着代码。

问题在那里呢?认真看运行结果,是不是发现好像有两个定时器在运行呢?没错,就是有两个定时器在运行了。

原来是我的运行结果用了Cache来保存,运行的站点是个免费的国外空间,估计我们半夜的时候是人家那里烈阳当头的时候,所以出现了内存紧张,我存着结果的Cache给回收了。Cache给回收之后,下次有人访问的时候就会重新设置一个定时器。

于是发现了一个题外话,有个哥们在1:51分的时候来关顾过我的网站,哦,这个网站运行环境的时候估计和我们有12个小时的时差。

问题描述出来了,那接下来就是解决

小弟不用Cache了,直接存在一个文本文件里。

于是问题解决了,并且我改了定时器的运行周期,半小时一次,然后我们继续等待测试结果吧。

最后,我对代码做了点修改,修改的范围在53到58行之间,之前有使用的孩纸,就重新复制粘贴下吧,没有的话就不用管这句话了

更新说明(2013-07-28 9:33)

重载一个构造函数

WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID)

自己开发能在asp.net项目正常使用的定时器WebTimer,让定时器听话起来的更多相关文章

  1. 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)

    最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...

  2. ASP.NET项目开发

    ASP.NET项目开发 1.C/S模式 (client 客户端 server 服务器):QQ.证券.酷狗.旺旺...需要下载响应软件: 工作原理:客户端请求--ASP.net服务器端应用(<-- ...

  3. 利用fis3自动化处理asp.net项目静态资源时遇到的一个编码问题

    fis3是一款强大的前端自动化构建工具,提供了很多非常实用的功能,具体参考http://fis.baidu.com/,使用该工具需要安装node环境. 最近在部署网站的时候尝试了一下使用该工具对前端资 ...

  4. (0)ASP.NET Core 简单介绍 和开发环境搭建 - ASP.NET从MVC5升级到MVC6

    ASP.NET从MVC5升级到MVC6 总目录 ASP.NET Core 首先,ASP原本只是一种技术,这种技术从上个世纪90年代就有了. Active Service Page 和 Java Ser ...

  5. 采用Opserver来监控你的ASP.NET项目系列(一、Opserver监控的简介与平台搭建)

    前言 之前有过2篇关于如何监控ASP.NET core项目的文章,有兴趣的也可以看看. 今天我们主要来讲讲如何监控我们的ASP.NET项目. 首先我们来介绍一下,什么是Opserver,它是Stack ...

  6. Asp.Net项目的部署到Linux中(Linux + Jexus+Nginx )

    因为老项目用的Asp.Net Web API技术开发部署到Window系统上,而新项目用的是.Net Core部署到Ubuntu系统中,所以在管理切换上有些不便.于是决定将老项目的测试服部署到Ubun ...

  7. Visual Studio 2013新建ASP.NET项目使用Empty模板,在页面中使用验证控件出错的解决方案

    Visual Studio 2013新建ASP.NET项目使用Empty模板,在页面中使用验证控件,运行页面,会出现如下的错误: 错误原因 VisualStudio 2012(或2013) WebFo ...

  8. 逐步改用 IronPython 开发你的 ASP.NET 应用程序

    IronPython for ASP.NET 的 CTP 已经发布有一段时间了,我们在看了官方提供的范例之后,相信对一个 ASP.NET 应用程序中完全使用 IronPython 开发还是有一些担心的 ...

  9. 远程调试 Asp.Net 项目

    项目部署到产品环境后,难免会发生一些故障,有一些可以在本地测试环境中直接重现,而有一些则无法重现.对于可以在本地测试环境中重现的Bug,开发人员往往能够很迅速地进行问题排查.而对于无法重现的Bug,就 ...

随机推荐

  1. nRFgo Studio 和 Nrfjprog 无法找到JLinkARM.dll的解决方法

    Segger在第一次安装的时候,会在注册表中添加安装路径的字段,nRF的两个软件就根据这两个注册表字段来寻找JLinkARM.dll.而当你卸载/更新Segger的时候,注册表的相关的字段是不会被修改 ...

  2. Linux mmc framework2:基本组件之queue

    1.前言 本文主要介绍card下queue组件的主要流程,在介绍的过程中,将详细说明和queue相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API 2.1 struct ...

  3. oracle数据库自增主键重复

    select max(t.id) from T_PLAT_ENUM_VALUE tdrop sequence T_PLAT_ENUM_VALUE;create sequence T_PLAT_ENUM ...

  4. linux添加定时任务crond

    1.crontab –e:编辑当前定时任务 保存完重新crond : service crond restart 2. crontab用法 crontab –e : 修改 crontab 文件,如果文 ...

  5. saltstack自动化运维系列⑤之saltstack的配置管理详解

    saltstack自动化运维系列⑤之saltstack的配置管理详解 配置管理初始化: a.服务端配置vim /etc/salt/master file_roots: base: - /srv/sal ...

  6. centos中创建自动备份Mysql脚本任务并定期删除过期备份

    背景: OA系统数据库是mysql,引擎为myisam,可以直接通过拷贝数据库文件的方式进行备份 创建只备份数据库的任务: 创建保存mysql数据库备份文件的目录mysqlbak mkdir /hom ...

  7. cacti系列(二)之cacti添加对tomcat服务器的监控

    cacti添加对tomcat的监控 1.首先下载监控tomcat的模板 TomcatStats-0.1.zip    2.导入模板 (cacti_host_template_tomcat_server ...

  8. Linux中 Lua 访问Sql Server的配置方法

    一.背景说明: 通过lua脚本实现对SQL Server数据库的操作. 二.具体设定: 安装流程图:如果是使用Lua连接SQL Server,从上到下则需要安装lua -> luaSQL-ODB ...

  9. 分布式调用技术 RPC VS REST

    一 分布式调用大体上就分为两类,RPC式的,REST式的,两者的区别主要是就是: 1. RPC是面向动作的(方法调用) 2. REST是面向资源的(URL表示资源,HTTP动词表示动作) 从变现形式来 ...

  10. 容器平台选型的十大模式:Docker、DC/OS、K8S 谁与当先?【转】

    网易企业服务2017-10-13 无论是在社区,还是在同客户交流的过程中,总会被问到到底什么时候该用 Docker?什么时候用虚拟机?如果使用容器,应该使用哪个容器平台? 显而易见,我不会直接给大家一 ...