在ASP.NET中调度作业(自动发送电子邮件)

时间:2013-10-11 05:36:52

标签: asp.net c#-4.0 global-asax timer-jobs

我正在开发一个ASP.NET(带有sql server)应用程序。我的要求是以特定的时间间隔从主机Web服务器(在我的情况下,来自Godaddy的Windows共享主机)发送电子邮件 - 这些可能是每天或每周或每月。无法使用Cron选项卡,因为它是在Linux主机上运行的Linux命令。 Godaddy的共享主机没有任何任务计划工具。我已经尝试了很多次但是无法获得成功。我已经使用过这三个代码。

首次尝试:

<%@ Application Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Threading" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Timers" %>
<script runat="server">    

    void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        Thread timerThread = new Thread(TimerForNotification);
        timerThread.IsBackground = true;
        timerThread.Priority = ThreadPriority.Highest;
        timerThread.Start();    
    }

    void TimerForNotification()
    {
        //Code that runs on application startup
        System.Timers.Timer timScheduledTask = new System.Timers.Timer();
        timScheduledTask.Interval = 1000 * 60 * 60;   //TimeSpan.FromMinutes(30).Minutes * 1000 * 60;
        timScheduledTask.Enabled = true;
        timScheduledTask.Elapsed += new System.Timers.ElapsedEventHandler(timScheduledTas_Elapsed);       
    }

    void timScheduledTas_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        ConnectionStringSettings conn = ConfigurationManager.ConnectionStrings["myshop_con"];
        SqlConnection con = new SqlConnection(conn.ConnectionString);
        SqlCommand cmd = con.CreateCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "insert into dbo.tblUserDetail(UName)VALUES('" + DateTime.Now.ToString() + "')";
        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();  
    }    

</script>

第二次尝试:

<%@ Application Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Threading" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>


<script runat="server">    

    public class TimerStarter
    {
        private static System.Threading.Timer threadingTimer;
        public static void StartTimer()
        {
            if (null == threadingTimer)
            {
                threadingTimer = new System.Threading.Timer(new TimerCallback(DoActions), HttpContext.Current, 0, 3600000);
            }
        }
        private static void DoActions(object sender)
        {
            ConnectionStringSettings conn = ConfigurationManager.ConnectionStrings["myshop_con"];
            SqlConnection con = new SqlConnection(conn.ConnectionString);
            SqlCommand cmd = con.CreateCommand();
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "insert into dbo.tblUserDetail(UName)VALUES('" + DateTime.Now.ToString() + "')";
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();  
        }

    }


    void Application_Start(object sender, EventArgs e) 
    {
        TimerStarter.StartTimer();
    }
</script>

第三次尝试:

<%@ Application Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Threading" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>


<script runat="server">    
    private void NightlyProcess(object o)
    {
        ConnectionStringSettings conn = ConfigurationManager.ConnectionStrings["myshop_con"];
        SqlConnection con = new SqlConnection(conn.ConnectionString);
        SqlCommand cmd = con.CreateCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "insert into dbo.tblUserDetail(UName)VALUES('" + DateTime.Now.ToString() + "')";
        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();  
    } 


    void Application_Start(object sender, EventArgs e) 
    {
        System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(NightlyProcess);
        System.Threading.Timer theTimer = new System.Threading.Timer(tcb, null, GetTimerInitialDelay(20, 40), GetTimerRepeatDelay(24));          
    }

    private long GetTimerInitialDelay(int hours, int minutes)
    {
        long startMS, repeatMS, currentMS;
        startMS = (1000 * 60 * 60 * hours) + (1000 * 60 * minutes);
        repeatMS = GetTimerRepeatDelay(24);

        DateTime now = DateTime.Now;
        long currentHours = 1000 * 60 * 60 * now.Hour;
        long currentMinutes = 1000 * 60 * now.Minute;
        long currentSeconds = 1000 * now.Second;
        long currentMilliSeconds = now.Millisecond;
        currentMS = currentHours + currentMinutes + currentSeconds + currentMilliSeconds;
        long delay = startMS - currentMS;
        if (delay < 0)
        {
            return repeatMS + delay;
        }
        else
        {
            return delay;
        }
    }

    private long GetTimerRepeatDelay(int hours)
    {
        long repeatMS;
        repeatMS = 1000 * 60 * 60 * hours;
        return repeatMS;
    }
</script>

如何以这些间隔发送这些电子邮件?

2 个答案:

答案 0 :(得分:0)

如果没有在后台运行某种任务调度程序或Windows服务,您无法实现的目标。

您可以尝试做的是创建一个网页,当被请求时会发送一定数量的电子邮件,然后使用某些第三方ping服务或从本地PC运行的一些非常简单的脚本来调用此页面。

请注意,这只是一种解决方法,可靠的解决方案需要在具有VPS或专用服务器托管的服务器上进行更多访问。

您可以尝试的另一件事是某种第三方服务,它将为您发送电子邮件。你可以试试邮件黑猩猩 - 他们有免费版本,每月有限量的电子邮件,你也可以使用一个API。

答案 1 :(得分:0)

很老的问题,但可能会帮助一些新的读者。 在ASP.NET中,我们可以模拟Windows服务来运行预定作业。

这很奇怪,但缓存项目对于此目的非常有用。

逻辑非常简单而且不同。

  1. 创建缓存对象

    private const string DummyCacheItemKey = "GagaGuguGigi";
    
    protected void Application_Start(Object sender, EventArgs e)
    {
         RegisterCacheEntry();
    }
    
    private bool RegisterCacheEntry()
    { 
      if( null != HttpContext.Current.Cache[ DummyCacheItemKey ] ) 
           return false;
    
      HttpContext.Current.Cache.Add( DummyCacheItemKey, "Test", null, 
      DateTime.MaxValue, TimeSpan.FromMinutes(1), 
      CacheItemPriority.Normal,
      new CacheItemRemovedCallback( CacheItemRemovedCallback ) );
    
      return true;
    }
    
  2. 删除缓存对象后,引发回调函数以运行预定作业。

    public void CacheItemRemovedCallback(string key, 
                                     object value, CacheItemRemovedReason reason)
    {
      Debug.WriteLine("Cache item callback: " + DateTime.Now.ToString() );
      HitPage()
    // Do the service works
    
    DoWork();
    }
    
  3. 在回调功能上,您必须再次设置缓存。为此,创建一个虚拟页面并通过webclient访问。

    private const string DummyPageUrl = 
               "http://localhost/TestCacheTimeout/WebForm1.aspx";
    
    private void HitPage()
    {
        WebClient client = new WebClient();
        client.DownloadData(DummyPageUrl);
    }
    
  4. 在Application_BeginRequest上检查它是否是虚拟页面。

    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        // If the dummy page is hit, then it means we want to add another item
    
        // in cache
    
         if( HttpContext.Current.Request.Url.ToString() == DummyPageUrl )
         {
            // Add the item in cache and when succesful, do the work.
    
            RegisterCacheEntry();
         }
     }
    
  5. Here is the details how you can schedule your activities with pure ASP.NET