首页 新闻 赞助 找找看

高分 System.Threading.Timer 失效

1
悬赏园豆:100 [已解决问题] 解决于 2012-09-02 14:43
    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 了。查看日志,没有写,压根没执行。

各位大侠,我的定时器有什么问题,帮忙看看。一般什么情况下 会失效。

问题补充:

MSDN上 看到这句,时间太久了,被回收了? 我的事静态字段,不应该啊,各位帮忙看看

Qlin的主页 Qlin | 老鸟四级 | 园豆:2403
提问于:2012-08-29 14:45
< >
分享
最佳答案
0
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);
        }
}

试试我这个,已经在项目里用了一段时间了,可以稳定运行。

收获园豆:35
向往-SONG | 老鸟四级 |园豆:4853 | 2012-08-29 15:33

谢谢 ,搬过来 试试

Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:37

我的,调式的时候,间隔时间短,都可以,就是间隔1天,不触发,有没有遇到 这种问题,
我的时间设置有没有问题。

Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:57

@Qlin: 

静态字段貌似也会有问题,Application里我也放了一份。

像你这种间隔长,而且那个时候没人访问的话,很可能会有问题的。

可以把间隔弄小(5分钟之类),如果不是23点就给网站发下请求,是23点就执行任务。

如果能从网站抽出来,最好还是用windows服务。

向往-SONG | 园豆:4853 (老鸟四级) | 2012-08-29 16:51
其他回答(3)
0

timers.Start();

收获园豆:5
jason2013 | 园豆:1998 (小虾三级) | 2012-08-29 14:58

没有 Start方法哦

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:03
0

我看你这里有个application_start方法,莫非你是在一个web程序里去启动一个定时任务?如果是的话你就被坑了。web程序的Application_Start方法并不是在应用程序池启动的时候执行,而是在站点第一次被访问的时候执行。也就是说如果你一个网站启动之后3个小时内都没有人访问,那么这个方法就一直不会执行。定时任务看起来很复杂其实实现起来很简单,你自己写个小程序(比如一个控制台exe程序),在你的程序里,你只需要实现业务逻辑,不需要去关心任务什么时候被发动,每隔多久执行一次这类“计划”。然后你用windows的计划任务,去定时启动你的程序就可以了。

收获园豆:20
水牛刀刀 | 园豆:6350 (大侠五级) | 2012-08-29 14:59

对的,是web程序,我的站点现在是 测试版本,现在有测试人员每天都在测试,肯定有人访问的。

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:02

Application_Start 原来以为是 站点启动时或者重启时,就执行,学习了

支持(1) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:09

现在 是每个 大菜单一个网站,已经有不少win服务和控制台,现在闲太多了,想改成线程方式,简单点,哎 就是不执行。

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:19

@Qlin: 既然保证有人访问,你改成这样试试:

while (true)
{
      //做一些事情
      Thread.Sleep(24小时);
}
支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-08-29 23:43
0
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);
收获园豆:20
慧☆星 | 园豆:5640 (大侠五级) | 2012-08-29 15:19
          autoEvent.WaitOne(timeStart, false);
          timer.Change(0, timeCount);

大侠这句autoEvent.WaitOne(timeStart, false);啥意思

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-08-29 15:22

@Qlin: 线程等待“距离 23:59 有多少毫秒”,然后change间隔时间,开始从每天的“ 23:59 ”每间隔24小时执行一次

支持(0) 反对(0) 慧☆星 | 园豆:5640 (大侠五级) | 2012-08-30 10:47
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册