Dynamically Creating Scheduled Tasks In An ASP.NET Website - c#

I am in need of some advice on the best approach to dynamically creating some form of scheduled task at web application level. The scheduled task will be pulling information from an external API endpoint to store within a database at regular intervals until a specific end time.
Normally, I would create a Windows Service that will carry out this job for me. Unfortunately, the site administrator could create multiple tasks to query different criteria from the external API. So there could be multiple tasks running.
I have been working on implementing a background worker thread that runs on a timer. Would this be the best approach? Or would using something like Hangfire or Quartz.net be a better solution to ensure my background process is constantly running?
I don't know if it's feasible inside a web application to be ensure a task can constantly be run when required for a specific duration of time.

I tried to use Hangfire and Quartz.Net and in my opinion both of them are very good for scheduling task. Hangfire has a good interface for managing scheduled tasks, but as I encountered some problems after publishing the application on IIS, I switched to use Quartz.Net which works perfectly with Keep Alive Service For IIS 6.0/7.5. So, for using Quartz.Net you might have a look at Scheduled Tasks In ASP.NET With Quartz.Net. On the other hand, in order to make your published application to be alive after application pool recycling, IIS/Application restarting, etc. just install Keep Alive Service For IIS 6.0/7.5 on the server to which you publish your application. For detailed information regarding to these problems have a look at my answers on the pages below:
Quartz.net scheduler doesn't fire jobs/triggers once deployed
execute a schedule with quartz in visual start now with interval 24 hours
Hope this helps...

Related

Preforming scheduled tasks in C# .NET MVC Application

I'm trying to implement a logic for my .NET MVC application where I would trigger scheduled tasks in my application on a following basis:
First scheduled task to run from 00 am to 1 am in the morning
Second scheduled task to run from 1:10 am to 08:00 am in the morning
Third scheduled task to run from 8:15 am to 11:15 pm every 1 hour
This would repeat every day 365 days a year...
Which mechanism in .NET or external library could I use to implement this the easiest way with little code?
I was trying to implement it with Quartz.NET library but I didn't like it at all, I had two scheduled tasks running where one would never run at all for the scheduled time...
You don't want to be performing long running and recurring background tasks in your web application for multiple reasons. You may go through the following blog post which outlines them very well.
I would recommend you moving this logic into a separate Windows Service or even a Console Application whose runs could be scheduled with the Windows Task Scheduler at the desired intervals.
The benefit of this is that you will be off-loading your web application from doing long running tasks which will be consuming precious resources from your webserver. Of course both the webserver and the worker service could share a common centralized datastore or messaging layer in order to communicate if necessary.
For scheduling tasks in ASP.NET MVC you have several options:
3rd party libraries like FluentScheduler, HangFire or Quartz.net.
Since .Net 4.5.2 there is QueueBackgroundWorkItem, a native way to schedule work in the background. Here is a guide on how to use it with ASP.NET MVC.
Azure services for background workloads and scheduled tasks. There are a couple of those aimed at different tasks, here is an overview of them.
Be careful if you try to implement a custom solution yourself, as any exception in a thread not associated with a request would halt the entire process.
Visual Cron is a decent task scheduler you can use. We use it, calling service methods on our asp.net / mvc / webapi servers.
http://www.visualcron.com/
There are some ways that you can create a scheduled task.
1- Create a WebApi and call it by local console or windows service application in period of time.
2- Using 3rd party libraries like FluentScheduler, HangFire or Quartz.net as Andreas said. it has its own side effects though.
3- If Sql server is used in your application, you can create a procedure for your task and put it on a job in Sql server. you can even use C# for your function if CLR is enabled in Sql Server,
If I want to choose, I will choose Sql Server jobs.
I had similar problem with my ASP.NET MVC App, I Wanted to do some works in special times and finally I could find a way.
My solution was Plesk scheduels task feature, as where the most windows servers use plesk control panel You can publish your app on a windows server with plesk CP and create a new actionresualt in your MVC App and write Your codes that want to execute them in special times.
By plesk scheduels tasks create a new task and call your Url with a cron that You made it, You can make many crons.
If I Could not explain It very well You can search about Plesk Schedueled Tasks on the Internet, You can find many good answers.

ASP.NET global background worker thread

I would like to create a background thread to pull data from another server periodically and send out real time email alerts to users.
Requirement:
The worker should never time out.
The worker should be running on a separate thread which means the server should still be able to handle user's requests while it is running
The worker should not be created per request but rather as a global thread which will be running when the server starts
I know it is a bad idea to create a background thread per request, but what is the best practice for a global backgroundworker thread?
Thanks in advance
Edited:
I am using Windows Azure to host the site, so I dont think I can create a windows service to run the task
Usually, you don't run such tasks in the web application itself as the application pool will be shut down after some time of inactivity depending on the configuration of the environment.
To make this work in a reliable way, create a separate application that periodically retrieves the data and sends the alerts. There are several ways to achieve this:
A very lightweight approach would be to create a console application and have a scheduler (e.g. Windows task scheduler) run it periodically.
A more sophisticated way is to create a Windows service that is started when the system starts and periodically executes the task.
If your application is integrated into a specific environment, there might already be a scheduling component available, e.g. in SharePoint you can implement jobs and let the Timer service run these.
I needed something similar to build scrapers. What I did is use the .Net ThreadPool class to send async http requests. I built a wrapper for building async requests with state object and then call:
ThreadPool.QueueUserWorkItem(new WaitCallback(asyncWrapper.BeginGetMethod), asyncStateObject);
Most people would recommend you to work with a Windows Service to accomplish it. However, a reasonable way to do this would be using a scheduling framework like Quartz .NET:
http://quartznet.sourceforge.net/
That way, if you think about it, your application deployment would even be easier - no win services or EXEs to deploy.
So If you decide to do it and run it embedded in your ASP.NET application, then you can start utilize it in the Global.Asaxfile, at Application_Start(), like this:
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "RemoteServer";
// set thread pool info
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
ISchedulerFactory sf = new StdSchedulerFactory(properties);
IScheduler sched = sf.GetScheduler();
sched.Start();
Typically web servers are designed for serving up web pages. Requests come in, HTML pages (among other things) go out. Unless you have full control over the server, what you are trying to do will be hard to achieve.

MVC - Run scheduled task even if nobody logs into app

I have a hosted ASP.NET MVC5 web app. Is there any way to get the app to run a "scheduled" task even if nobody logs into the app? Or is my only choice to use the App Start when the app first runs?
I need to send an email to my users first thing each morning. Is there a reasonable way to do this with the MVC5 app or am I going to have to set up a Windows service?
Most people recommend a windows service. However, a reasonable way to do this would be using a scheduling framework like Quartz .NET
http://quartznet.sourceforge.net/
I prefer this because then my jobs/schedules travel with my application and when I deploy on a new box I don't have to setup a service or anything, everything is embedded in the MVC5 application. Quartz also has the ability to sync between servers via a db if you have a load-balanced environment (like I do) and it works well enough for me. Also using the DB as the job store makes sure that jobs persist between deployments and application restarts because by default jobs are in memory.
I would not involve an email sending job with MVC application, since if you think about it, an MVC application concern is to work by the Request-Response model, on which scenario do you see it start a new job?
If you have an access to your users emails, just create a simple Console Application or a Windows Service to do that work and set a scheduling for it using the Windows Task Scheduler or any other task scheduling tool.
In addition, if you're enforced to do it within your MVC application:
Read is a nice old post by Jeff Atwood about how to create a job inside ASP.NET application: Easy Background Tasks in ASP.NET
Create and schedule a call to an Action in your MVC application that will do that email sending work
Use Quartz.NET third-party library for creating scheduled background tasks in
Web-Applications
Don't use a Windows service, instead you should use the Windows Task Scheduler.
Just create a Console Application and register it in the scheduler.
You can create a singleton and in your ApplicationStart(); that will launch itself every 24h and then send emails. It will include locking that particular thread for 24h.
It's a very bad approach but it seems that you don't have any other options when you're on shared hosting with no access to actual system.
I think the question comes down to, do you need the ability to start/stop the service and have the webapp still running?
I personally try to avoid setting up a windows service because it adds another layer of complexity that can break/not work. If you use quartz or just a basic timer in your web app, the scheduling is guaranteed to run when your app runs.
With in-app scheduling you can install your webapp with a simple file copy.
Sure, there are situation when you need to do heavy background jobs, then you might want to consider a separate batch job project with a windows service... but for sending out a couple of email, just use in-app scheduling.
The common way to do this is with the Windows Task Scheduler.
The problem with calling START or some other command line parameter is the opened browser may never close or it might close when the task times out.
I wrote a console app to make a call to a website and wait for a response.
Imports System.IO
Imports System.Net
Module Module1
Sub Main()
Dim sw As New Stopwatch
sw.Start()
Try
Dim args = Environment.GetCommandLineArgs.ToList
If args.Count = 1 Then Throw New Exception("WebsiteWaitResponse url [user] [password]")
Console.WriteLine("{0:c} WebsiteWaitResponse {1:g}", sw.Elapsed, Now())
Dim web As New WebClient
If args.Count > 2 Then web.Credentials = New NetworkCredential(args(2), args(3))
Dim results = web.DownloadString(args(1))
Console.WriteLine(results)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Console.WriteLine("{0:c} WebsiteWaitResponse Complete", sw.Elapsed)
End
End Sub
End Module
Create a scheduled task which calls this app with command line parameters as follows:
MyConsoleApp url [userid] [password]
where [userid] and [password] are optional and used for ntlm authentication
MyConsoleApp http://mywebsite/controller/function mydomain\myuser mypassword
Hangfire to the rescue. This is perhaps the easiest and more reliable way to achieve this task. It comes with a dashboard that makes managing and monitoring your background tasks effortless.
Please check the below URL, using which you can make sure that your web application is always up, even if no body is logged into your application, or if your application is idle for long time
You just need to configured your server per below and make sure to start your jobs.
http://developers.de/blogs/damir_dobric/archive/2009/10/11/iis-7-5-and-always-running-web-applications.aspx

Does each azure instance run cron?

I am developing an ASP.NET application, which will be uploaded on Azure. If I have multiple instances on Azure and I want to run a cron job that will be necessary for my application. Then, I just want to confirm if that cron job will be run only one time or each instance will run that cron by itself?
For example: If I have 4 instances of cloud service on Azure and my application runs a cron job every day at 11:00 PM. So, I just want to confirm if that cron will be run only one time or each instance will run that cron on its own (i.e. cron will be run 4 times or we can say one time by each instance)?
Please suggest.
So far I've found 3 ways to do cron jobs BUT they all require some level of managing the multiple instances possibly running the tasks.
The choices I've used so far:
Windows Task Scheduler - create a startup script that adds the user and task the schedules it. More information here: Running Azure startup tasks as a real user and here: Building a Task Scheduler in Windows Azure
Using Quartz.Net - this I started with, but then moved to the windows task scheduler, but it may work for you since you can customize stuff easier. More information here: Using Quartz.net to Schedule Jobs in Windows.Azure Worker Roles
Using the new job scheduler in Mobile Services. I have not used this one, but when I read this blog: Job Scheduling in Windows Azure late last year I put it on my mental list to look at next time I need a job scheduler. It's still a little new, but it also may help you.
In your example, all 4 instances will try and run the cron job. If you would want to have only one instance run the job, you would need to implement some kind of "locking" mechanism. What normally folks do is that each instance will try and acquire a 1 minute lease on the same blob. Only one instance will be successful in acquiring the lease. You can put the logic that only the instance which is able to acquire the lease is executing that cron job.
As other users said, there are many ways to do that. I add a couple of suggestions. Have you developed a Cloude service web role or a Web site. If the former, the easiest way is to create also 1 worker role (only one) and run tasks from there. It the latter, you need an external "trigger": you can use Scheduler (by Aditi). You can get it from the Azure store (there is a free flan).
If a role (Web/Worker/VM role) has multiple instances, it means that you got the same account of Windows Server VMs (the version depends which guest OS version you configured). Each VM will run exact the same code of your application (like a ASP.NET Web Application), all requests to this role will be load-balanced and one of the VMs will sever the request based on round-robin policy.
So if your cron job only needs to be run only once, as Guarav said, you need some lock mechanism to let one of your role instances run it.

Is there a way to have code run on a time schedule in an ASP.NET web app?

I have an ASP.NET web app providing access to a database on the server. What I need is a way to run code in the background on a given schedule that auto-updates the server database from another source.
I know how to do this in a windows app by adding a timer, linking up a function to the timer tick event and starting the timer. I do not know how to do this in a web app.
Is there a start-up event for a web app or somewhere where I can start this background process regardless of whatever any users are doing on the site?
You should not do this in an ASP.NET website - this is a major no-no. You are correct in thinking to use a timer on a background .exe. You should look into creating either a Windows Task (a console .exe executed by the server task timer), or a Windows Service. I would suggest the Windows Service as that is standard practice.
If you have access to the computer hosting your site I would write a little app that was run from the Task Scheduler.
The web server is not meant to handle long-running background tasks. It's the wrong tool.
If you dont have access to the hosting computer then I would suggest building some kind of interface whereby another computer rebuilt the database and uploaded it. I'm using the terms "interface" and "upload" in the loosest, broadest sense - apply your own definition.
I was searching for a solution myself couple of months ago, and even though I haven't found enough time to try it so far, I guess I can share the link with you. Maybe you'll find it helpful.
If yes, please, let me know here.
http://quartznet.sourceforge.net/
How to use Quartz.net with ASP.NET
you can use Windows Service or use Timer Control (In the Ajax Category)
Or
As other answers have stated, doing this full function - updating a database and scheduling it as an ASP.NET app is using the wrong tool for the job.
ASP.NET can be used to update a database - that's perfectly valid. Where it breaks down is in the timer. ASP.NET apps aren't meant to be long-running, which is necessary for the timer to work.
If you can do it, I'd strongly suggest using the approach others have suggested - a Windows Service or a Scheduled Task.
However, if you have no access to the actual server, other than to post ASP.NET code - you can't install a service and you can't set up a Windows app to run on a scheduled basis, here's an out-of-the box idea.
Set up a web service or ASPX page that does the update, and then call that page from a scheduled task on a machine you DO control.
So if this was at http://www.someserver.net/updatedb.aspx, there's no reason you can't set a scheduled task on your own PC to call that URL.
I'd consider this a last-ditch solution to be used only if you can't do one of the other options.
The global.asax.cs file has a method that is fired when your application starts: Application_Start. You can hook up your timer method in that event. Just beware, depending on how IIS configured, your app pool may shutdown. For example, if no one hits the site in 20 minutes for example. Just make sure if you HAVE to have this run every X minutes that you have IIS configured to ALWAYS be running and start your app. This is harder than it sounds. In the end, you may want to go with a regular windows scheduled task.

Categories