如何使用asp.net mvc每天运行一次函数?

时间:2012-09-06 11:41:03

标签: asp.net-mvc scheduled-tasks

我是ASP.NET MVC的新手。我熟悉其他MVC框架,如Rails和PHP MVC FM。

我需要每天在ASP.NET MVC中运行一次函数 - 我应该怎么做?我想要这个函数来更新数据库。

在Linux中,我可以将URL放到Cron每天访问一次的服务器上,但我不知道在Windows中执行此操作的最佳方法。

1 个答案:

答案 0 :(得分:0)

基本上你需要在web.config文件中添加两个AppSettings:

<appSettings>
  .
  <add key="TimerStartTime" value="09:00:00 PM"/>
  <add key="TimerIntervalInMilliseconds" value="3000000"/>
</appSettings>

然后,在Global.asax.cs文件中修改并添加:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
// Added the following for the timer related code
using System.Diagnostics;
using System.Timers;
using System.Web.Configuration;

namespace TestVSOnline01
{
    public class MvcApplication : System.Web.HttpApplication
    {
        // Added this class visible variable to hold the timer interval so it's not gotten from the
        // web.config file on each Elapsed event of the timer
        private static double TimerIntervalInMilliseconds =
            Convert.ToDouble(WebConfigurationManager.AppSettings["TimerIntervalInMilliseconds"]);

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            // Added the following within the Application_Start() procedure:
            // *******************************************************************************************
            // The values used in this example will cause your processes to run sometime
            // between 09:00:00 PM and 09:05:00 PM, with the timer Elapsed event being raised
            // every 300000ms (5 minutes)
            //
            // The following AppSettings were added to Web.config:
            //    TimerStartTime
            //    TimerIntervalInMilliseconds
            // You can use a simple text editor to change your start time and/or timer interval without
            // having to modify your code, recompile, and republish it. 
            //
            // The shorter the interval, then smaller the time window in which the processes will run, but
            // the more frequently all of this code and event firing is happening. But you could set the
            // interval to 1000ms and have you events run right at the time specified.
            //
            // !!! NOTE: The web.config file is not designed for constant updates. When an ASP.NET
            // !!! application launches a watch is put on the web.config file. ASP.NET will detect if the
            // !!! web.config changes while the application is running. When ASP.NET detects a change it
            // !!! will spin up a new version of the application with the new settings in effect. Any in
            // !!! process information, such as data kept in Session, Application, and Cache will be lost
            // !!! (assuming session state is InProc and not using a state server or database).
            // !!! (Source: http://odetocode.com/Articles/345.aspx)
            //
            // *******************************************************************************************

            // The Debug.WriteLine calls are for watching the progress in the Output Window
            // in Visual Studio - Remove or comment out if you like

            Debug.WriteLine(string.Concat("Application_Start Called: ", DateTime.Now.ToString()));

            // This will raise the Elapsed event every 'x' millisceonds (whatever you set in the
            // Web.Config file for the added TimerIntervalInMilliseconds AppSetting
            Timer timer = new Timer(TimerIntervalInMilliseconds);

            timer.Enabled = true;

            // Setup Event Handler for Timer Elapsed Event
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);

            timer.Start();
        }

        // Added the following procedure:
        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            // Get the TimerStartTime web.config value
            DateTime MyScheduledRunTime = DateTime.Parse(WebConfigurationManager.AppSettings["TimerStartTime"]);

            // Get the current system time
            DateTime CurrentSystemTime = DateTime.Now;

            Debug.WriteLine(string.Concat("Timer Event Handler Called: ", CurrentSystemTime.ToString()));

            // This makes sure your code will only run once within the time frame of (Start Time) to
            // (Start Time+Interval). The timer's interval and this (Start Time+Interval) must stay in sync
            // or your code may not run, could run once, or may run multiple times per day.
            DateTime LatestRunTime = MyScheduledRunTime.AddMilliseconds(TimerIntervalInMilliseconds);

            // If within the (Start Time) to (Start Time+Interval) time frame - run the processes
            if ((CurrentSystemTime.CompareTo(MyScheduledRunTime) >= 0) && (CurrentSystemTime.CompareTo(LatestRunTime) <= 0))
            {                
                Debug.WriteLine(String.Concat("Timer Event Handling MyScheduledRunTime Actions: ", DateTime.Now.ToString()));
                // RUN YOUR PROCESSES HERE
            }
        }
    }
}

清理干净,非常简单。下面的代码只是您需要添加到Global.asax.cs文件的简化版本(不要忘记添加web.config appsettings):

// Added the following for the timer related code
using System.Diagnostics; // Can remove this reference if you remove all the Debug.Writeline entries
using System.Timers;
using System.Web.Configuration;

// Add the following to the top of the main class, outside of any subroutines:
private static double TimerIntervalInMilliseconds = Convert.ToDouble(WebConfigurationManager.AppSettings["TimerIntervalInMilliseconds"]);

// Add the following to the end of the Application_Start() subroutine:
Timer timer = new Timer(TimerIntervalInMilliseconds);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();

// Added the following procedure:
static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {    
        DateTime MyScheduledRunTime = DateTime.Parse(WebConfigurationManager.AppSettings["TimerStartTime"]);
        DateTime CurrentSystemTime = DateTime.Now;
        DateTime LatestRunTime = MyScheduledRunTime.AddMilliseconds(TimerIntervalInMilliseconds);
        if ((CurrentSystemTime.CompareTo(MyScheduledRunTime) >= 0) && (CurrentSystemTime.CompareTo(LatestRunTime) <= 0))
        {                
            // RUN YOUR PROCESSES HERE
        }
    }