Background task in ASP webapp

I am new to C # and have recently created a small webapp using .NET 4.0. This application has 2 parts: one is designed for continuous operation and will continuously receive data from data resources on the Internet. Another refers to this query data for analysis. I struggle with the first part.

My initial approach was to create a Timer object that would perform a fetch operation (no matter what the operation does not matter here) every, say, 5 minutes. I would determine that the timer is on Application_Start and let it live after that.

However, I recently realized that applications are created / destroyed based on user requests (from my observation, they seem to be destroyed after some time of inactivity). As a result, my background activity will stop / stop monitoring me when I want it to work continuously, without any interruptions.

So here is my question : is this possible in webapp? Or do I absolutely need a separate Windows service for this kind of thing?

Thanks in advance for your precious help!

Guillaume

+6
source share
7 answers

While this is done in a web application, this is not ideal. this is achievable , given that the site is always up.

Here is an example: I create a Cache element in global.asax with an expiration date. After this period, dismissal occurs. You can receive data or something else in the OnRemove () event.

You can then set up a page call (preferably a very small one) that calls the code in Application_BeginRequest, which will add an expired cache element.

global.asax:

 private const string VendorNotificationCacheKey = "VendorNotification"; private const int IntervalInMinutes = 60; //Expires after X minutes & runs tasks protected void Application_Start(object sender, EventArgs e) { //Set value in cache with expiration time CacheItemRemovedCallback callback = OnRemove; Context.Cache.Add(VendorNotificationCacheKey, DateTime.Now, null, DateTime.Now.AddMinutes(IntervalInMinutes), TimeSpan.Zero, CacheItemPriority.Normal, callback); } private void OnRemove(string key, object value, CacheItemRemovedReason reason) { SendVendorNotification(); //Need Access to HTTPContext so cache can be re-added, so let call a page. Application_BeginRequest will re-add the cache. var siteUrl = ConfigurationManager.AppSettings.Get("SiteUrl"); var client = new WebClient(); client.DownloadData(siteUrl + "default.aspx"); client.Dispose(); } private void SendVendorNotification() { //Do Tasks here } protected void Application_BeginRequest(object sender, EventArgs e) { //Re-add if it doesn't exist if (HttpContext.Current.Request.Url.ToString().ToLower().Contains("default.aspx") && HttpContext.Current.Cache[VendorNotificationCacheKey] == null) { //ReAdd CacheItemRemovedCallback callback = OnRemove; Context.Cache.Add(VendorNotificationCacheKey, DateTime.Now, null, DateTime.Now.AddMinutes(IntervalInMinutes), TimeSpan.Zero, CacheItemPriority.Normal, callback); } } 

This works well if the scheduled task is fast. If this is a long process, you definitely need not to use it in your web application.

Until the first request launches the application ... it will continue every 60 minutes, even if there are no visitors on it.

+2
source

I suggest putting it in a windows service. You avoid all the hoops mentioned above, a large one that restarts IIS. The Windows service also has the following advantages:

  • It can automatically start when the server starts. If you are running IIS and restarting the server, you need to wait until the request is complete to start your process.
  • You can put this data extraction process to another computer if necessary
  • If you finish the load balancing on your website on multiple servers, you may accidentally get several data extraction processes causing problems.
  • It’s easier to manage the code separately (the principle of shared responsibility). It's easier to maintain code if it just does what it needs, rather than trying to trick IIS.
+2
source

Create a static class with a constructor by creating a timer event. However, as Steve Slock noted, IIS has a timeout that you will need to manipulate in order to maintain the site.

 using System.Runtime.Remoting.Messaging; public static class Variables { static Variables() { m_wClass = new WorkerClass(); // creates and registers an event timer m_flushTimer = new System.Timers.Timer(1000); m_flushTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnFlushTimer); m_flushTimer.Start(); } private static void OnFlushTimer(object o, System.Timers.ElapsedEventArgs args) { // determine the frequency of your update if (System.DateTime.Now - m_timer1LastUpdateTime > new System.TimeSpan(0,1,0)) { // call your class to do the update m_wClass.DoMyThing(); m_timer1LastUpdateTime = System.DateTime.Now; } } private static readonly System.Timers.Timer m_flushTimer; private static System.DateTime m_timer1LastUpdateTime = System.DateTime.MinValue; private static readonly WorkerClass m_wClass; } public class WorkerClass { public delegate WorkerClass MyDelegate(); public void DoMyThing() { m_test = "Hi"; m_test2 = "Bye"; //create async call to do the work MyDelegate myDel = new MyDelegate(Execute); AsyncCallback cb = new AsyncCallback(CommandCallBack); IAsyncResult ar = myDel.BeginInvoke(cb, null); } private WorkerClass Execute() { //do my stuff in an async call m_test2 = "Later"; return this; } public void CommandCallBack(IAsyncResult ar) { // this is called when your task is complete AsyncResult asyncResult = (AsyncResult)ar; MyDelegate myDel = (MyDelegate)asyncResult.AsyncDelegate; WorkerClass command = myDel.EndInvoke(ar); // command is a reference to the original class that envoked the async call // m_test will equal "Hi" // m_test2 will equal "Later"; } private string m_test; private string m_test2; } 
+1
source

I think you can achieve this using BackgroundWorker , but I would rather suggest you use the service.

0
source

Your application context works as long as your workflow in IIS works. There are some default timeouts in IIS when a workflow will be processed (for example, the number of minutes to wait (20) or regular intervals (1740).

However, if you configure these settings in IIS, you will be able to receive requests in real time, however, other answers to using the service will also work, just a question of how you want to implement.

0
source

I recently made a file upload function to load Access files into a database (not the best way, but just a temporary fix for a long-term problem). I solved this by creating a background thread that went through the ProcessAccess function and was deleted after completion.

If IIS does not have a parameter in which it kills the thread after a certain time, regardless of inaction, you should be able to create a thread that calls a function that never ends. Do not use recursion, because the number of open functions will eventually explode in you, but just write a loop (;;) 5,000,000 times so that it continues to work :)

0
source

The application initialization module for IIS 7.5 does exactly this type of init work. More information about the module can be found here. Application initialization module.

0
source

Source: https://habr.com/ru/post/890965/


All Articles