0

I have implemented an http module which will be fired on application start of my ASP.NET application

using System.Web;
using System.Threading.Tasks;
using System;
using System.Net.Http;

namespace BL.HttpModules
{
    public class MyCustomAsyncModule : IHttpModule
    {
        #region Static Privates

        private static bool applicationStarted = false;
        private readonly static object applicationStartLock = new object();

        #endregion

        public void Dispose()
        {

        }

        /// <summary>
        /// Initializes the specified module.
        /// </summary>
        /// <param name="httpApplication">The application context that instantiated and will be running this module.</param>
        public void Init(HttpApplication httpApplication)
        {
            if (!applicationStarted)
            {
                lock (applicationStartLock)
                {
                    if (!applicationStarted)
                    {
                        // this will run only once per application start
                         this.OnStart(httpApplication);
                    }
                }
            }
            // this will run on every HttpApplication initialization in the application pool
            this.OnInit(httpApplication);
        }

        public virtual void OnStart(HttpApplication httpApplication)
        {            
            httpApplication.AddOnBeginRequestAsync(OnBegin, OnEnd);
        }

        private IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData)
        {
            applicationStarted = true;
            var tcs = new TaskCompletionSource<object>(extraData);
            DoAsyncWork(HttpContext.Current).ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    tcs.SetException(t.Exception.InnerExceptions);
                }
                else
                {
                    tcs.SetResult(null);
                }
                if (cb != null) cb(tcs.Task);
            });
            return tcs.Task;
        }

        async Task DoAsyncWork(HttpContext ctx)
        {
            var client = new HttpClient();
            var result = await client.GetStringAsync("http://google.com");
            // USE RESULT
        }

        private void OnEnd(IAsyncResult ar)
        {
            Task t = (Task)ar;
            t.Wait();
        }

        /// <summary>Initializes any data/resources on HTTP module start.</summary>
        /// <param name="httpApplication">The application context that instantiated and will be running this module.</param>
        public virtual void OnInit(HttpApplication httpApplication)
        {
            // put your module initialization code here


        }

    }// end class
}// end namespace

I want to fire DoAsyncWork after each 5 minutes. Can you help me achieving that goal in that module?

Raghav
  • 8,772
  • 6
  • 82
  • 106
  • You do know that scheduled tasks of any kind inside asp.net is bad idea, don't you? – Alexei Levenkov Jun 05 '17 at 15:02
  • Possible duplicate of [Run async method regularly with specified interval](https://stackoverflow.com/questions/30462079/run-async-method-regularly-with-specified-interval) –  Jun 05 '17 at 15:02
  • @Amy i would disagree with that specific duplicate, the fact that this is ASP.NET changes the constraints on how you do repeating work, both solutions in the linked duplicate will not work long term on ASP.NET due to application pool recycling. – Scott Chamberlain Jun 05 '17 at 15:03

1 Answers1

0

There is no built in way in IIS to reliably do this, you need to use a external process or a 3rd party library to scheduled the work to be done. Hangfire is a very popular library that lets you do both in process and out of process scheduled tasks.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431