Планирование заданий в ASP.NET (автоматическая отправка электронной почты)

Я занимаюсь разработкой приложения ASP.NET (с сервером sql). Мое требование - отправлять электронные письма с хост-сервера (в моем случае это Shared Hosting от Godaddy) через определенные промежутки времени - это может быть ежедневно, еженедельно или ежемесячно. Вкладка 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 ответа

То, чего вы пытаетесь достичь, невозможно без какого-либо планировщика задач или службы Windows, работающей в фоновом режиме.

То, что вы можете попытаться сделать, - это создать веб-страницу, которая при запросе будет отправлять определенное количество электронных писем, а затем вызывать эту страницу, используя какой-либо сторонний ping-сервис или какой-нибудь очень простой скрипт, работающий на вашем локальном ПК.

Обратите внимание, что это только обходной путь, и для надежного решения требуется больший доступ на сервере с VPS или выделенным сервером.

Еще одна вещь, которую вы можете попробовать - это какая-то сторонняя служба, которая будет отправлять вам электронные письма. Вы можете попробовать почтовый шимпанзе - у них есть бесплатная версия с ограниченным количеством писем в месяц, а также есть API, который вы можете использовать.

Очень старый вопрос, но может помочь некоторым новым читателям. В ASP.NET мы можем моделировать Windows Service для запуска запланированных заданий.

Это очень странно, но элементы кэша очень полезны для этой цели.

Логика очень проста и отличается.

  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. При использовании функции обратного вызова вы должны снова установить кэш. Для этого создайте фиктивную страницу и зайдите через веб-клиент.

    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();
         }
     }
    

Вот подробности, как вы можете планировать свои действия с чистым ASP.NET

Другие вопросы по тегам