public static class OrderMgr { static Timer timer = null; public static void BootRun() { //创建一个定时器 TimerCallback timerDelegate = new TimerCallback(Task); DateTime dtS = DateTime.Parse("23:59"); //每天晚上 23:59 运行 long span = (dtS - DateTime.Now).Ticks; if (span < 0) dtS = dtS.AddDays(1); long timeStart = (dtS - DateTime.Now).Ticks / 1000; //距离 23:59 有多少毫秒 long timeCount = 1000 * 60 * 60 * 24; //每隔 24小时的 启动线程 timer = new Timer(timerDelegate, null, timeStart, timeCount); } static void Task(object obj) { ... } }
protected void Application_Start() { //启动定时器 OrderMgr.BootRun(); }
需求:每天晚上 23:59分钟执行一个函数。
现状:没有执行,调用的方法里都有写日志,也 try catch 了。查看日志,没有写,压根没执行。
各位大侠,我的定时器有什么问题,帮忙看看。一般什么情况下 会失效。
public class XXXXX { /// <summary> /// 校验时间 /// </summary> public static DateTime CheckTime = DateTime.Now; /// <summary> /// 停止发送 /// </summary> public static bool StopSend = false; /// <summary> /// 定时发送间隔时间 /// </summary> public static int Interval = 3 * 1000; /// <summary> /// 标识是否正在运行 /// </summary> public static bool IsRunning = false; private static int delay = 0; private static bool IsLock = false; private static System.Threading.Timer InnerTimer; /// <summary> /// 开始自动发送 /// </summary> /// <returns></returns> public static System.Threading.Timer StartAutoSend() { return XXXXX.StartAutoSend(0); } /// <summary> /// 开始自动发送 /// </summary> /// <param name="delay">自动发送开始的延时时间ms,程序启动时可添加延时</param> public static System.Threading.Timer StartAutoSend(int delay) { if ( //核对状态 !XXXXX.IsRunning || //核对时间,防止定时器意外终止,精确到分 XXXXX.CheckTime.ToString("yyyy-MM-dd HH:mm") != DateTime.Now.ToString("yyyy-MM-dd HH:mm")) { XXXXX.IsRunning = false; XXXXX.delay = delay; //如果定时器还存在,则销毁 if (XXXXX.InnerTimer != null) { XXXXX.InnerTimer.Dispose(); } XXXXX.InnerTimer = new System.Threading.Timer(XXXXX.CallBack, null, 0, XXXXX.Interval); } return XXXXX.InnerTimer; } /// <summary> /// 回调-发送 /// </summary> /// <param name="o"></param> private static void CallBack(object o) { //延时执行 if (XXXXX.delay > 0) { System.Threading.Thread.Sleep(XXXXX.delay); XXXXX.delay = 0; } //已经在执行了,就不再执行,直接执行完 if (XXXXX.IsLock) { return; } try { //锁定 XXXXX.IsLock = true; //发送 Send(); } finally { //设置校验时间 XXXXX.CheckTime = DateTime.Now; XXXXX.IsRunning = true; //解锁 XXXXX.IsLock = false; } } /// <summary> /// 发送 /// </summary> public static void Send() { } }
public class Global : System.Web.HttpApplication { .... protected void Session_Start(object sender, EventArgs e) { Application["XXXXXX"] = XXXXX.StartAutoSend(10 * 1000); } }
试试我这个,已经在项目里用了一段时间了,可以稳定运行。
谢谢 ,搬过来 试试
我的,调式的时候,间隔时间短,都可以,就是间隔1天,不触发,有没有遇到 这种问题,
我的时间设置有没有问题。
@Qlin:
静态字段貌似也会有问题,Application里我也放了一份。
像你这种间隔长,而且那个时候没人访问的话,很可能会有问题的。
可以把间隔弄小(5分钟之类),如果不是23点就给网站发下请求,是23点就执行任务。
如果能从网站抽出来,最好还是用windows服务。
timers.Start();
没有 Start方法哦
我看你这里有个application_start方法,莫非你是在一个web程序里去启动一个定时任务?如果是的话你就被坑了。web程序的Application_Start方法并不是在应用程序池启动的时候执行,而是在站点第一次被访问的时候执行。也就是说如果你一个网站启动之后3个小时内都没有人访问,那么这个方法就一直不会执行。定时任务看起来很复杂其实实现起来很简单,你自己写个小程序(比如一个控制台exe程序),在你的程序里,你只需要实现业务逻辑,不需要去关心任务什么时候被发动,每隔多久执行一次这类“计划”。然后你用windows的计划任务,去定时启动你的程序就可以了。
对的,是web程序,我的站点现在是 测试版本,现在有测试人员每天都在测试,肯定有人访问的。
Application_Start 原来以为是 站点启动时或者重启时,就执行,学习了
现在 是每个 大菜单一个网站,已经有不少win服务和控制台,现在闲太多了,想改成线程方式,简单点,哎 就是不执行。
@Qlin: 既然保证有人访问,你改成这样试试:
while (true) { //做一些事情 Thread.Sleep(24小时); }
TimerCallback timerDelegate = new TimerCallback(Task); DateTime dtS = DateTime.Parse("23:59"); //每天晚上 23:59 运行 long span = (dtS - DateTime.Now).Ticks; if (span < 0) dtS = dtS.AddDays(1); long timeStart = (dtS - DateTime.Now).Ticks / 1000; //距离 23:59 有多少毫秒 long timeCount = 1000 * 60 * 60 * 24; //每隔 24小时的 启动线程 timer = new Timer(timerDelegate, null, timeStart, 0); autoEvent.WaitOne(timeStart, false); timer.Change(timeCount, 0);
autoEvent.WaitOne(timeStart, false); timer.Change(0, timeCount);
大侠这句autoEvent.WaitOne(timeStart, false);啥意思
@Qlin: 线程等待“距离 23:59 有多少毫秒”,然后change间隔时间,开始从每天的“ 23:59 ”每间隔24小时执行一次