MVC3中的TimerCallback

时间:2012-03-29 16:36:29

标签: c# asp.net-mvc-3

我知道这个简单代码每隔午夜执行一个方法,我有一个共享主机(不可能创建一个Windows计划),但这不起作用。有什么想法吗?

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.DefaultNamespaces.Add("PhotoPremier.Controllers");

        var dt = NextAt(new TimeSpan(0, 0, 0)); //
        var timer = new Timer(new TimerCallback(callback), HttpContext.Current, dt - DateTime.Now, TimeSpan.FromHours(24));

    }

    static void callback(Object stateObject) 
    {
        DbLayer.ContestManager cm = new DbLayer.ContestManager();
        cm.UpdateAllPhotosInContest();
    } 

    DateTime NextAt(TimeSpan time)
    {
        DateTime now = DateTime.Now;
        DateTime result = now.Date + time;

        return (now <= result) ? result : result.AddDays(1);
    }

3 个答案:

答案 0 :(得分:1)

这可能是由于共享主机中的IIS设置。

默认情况下,IIS配置会在一定时间后关闭应用程序,而无需任何人访问它。 IIS也会每隔几分钟回收一次应用程序池。

除非您能够控制此设置,否则您将很难保持应用程序处于活动状态并触发计时器的触发器。

为了澄清这种情况并建议其他替代方案,我给你以下链接:

http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

答案 1 :(得分:0)

我认为Unique解决方案是使用Quarts.Net Framework。

非常简单,在这里有一个简单的代码。

public class DailyJob : IJob
{
    public DailyJob() { }

    public void Execute( JobExecutionContext context )
    {
        try {
            DbLayer.ContestManager cm = new DbLayer.ContestManager();
            cm.UpdateAllPhotosInContest();
        } catch( Exception e ) {
            //Handle this please
        }
    }

    public static void ScheduleJob( IScheduler sc )
    {
        JobDetail job = new JobDetail("FinishContest", "Daily", typeof(DailyJob));
        sc.ScheduleJob(job, TriggerUtils.MakeDailyTrigger("trigger1", 0, 0));
        sc.Start();
    }
}

//Global.asax
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            /* HERE */ DailyJob.ScheduleJob(new StdSchedulerFactory().GetScheduler());
        }

答案 2 :(得分:0)

当我最近尝试做同样的事情时,我发现我的问题是在某个地方声明我的Timer对象,它会收集垃圾。如果您使计时器成为您的类的成员而不是在Application_Start中本地声明它,我认为原始海报的代码将起作用。

希望这有助于某人。