I want to have my website do a number of calculations every 10 minutes and then update a database with the results. How exactly do I set such a timer, i am assuming it would be in global.asax?
Doing something like that in a web application is somewhere between difficult and unstable to impossible. Web applications are simply not meant to be run non-stop, only to reply to requests.
Do you really need to do the calculations every ten minutes? I have found that in most cases when someone asks a question like this, they really just need the appearence of something running at an interval, but as long as noone is visiting the page to see the results, the results doesn't really need to be calculated.
If this is true in your case also, then you just need to keep track of when the calculations were done the last time, and for every request check if enough time has gone by to recalculate.
You'd be better off writing a separate non-UI application and then running that as a scheduled task.
Aside from (correct) statements about instability of web application for scheduled task execution, here's a strategy you could implement:
in global.asax, define application.onstart event in which create timer:
var dueTime = 5000;
var period = 5000;
var MyTimer = new Timer(new TimerCallback(MyClass.MyTaskProc), null, dueTime, period);
Application["MyTaskTimer"] = MyTimer;
this will pretty much take care of creating task and restarting it should application exit
ifs its strictly database calculations, keep it in the database. Create a stored proc that does what you want, then have SQL Server agent run that proc on a schedule.
the Cache solution in cagdas' answer works. I've used it. It's only downside is that it's difficult to turn it off if you need to suspend the timer for some reason. Alternate, but not quite identical solutions we've used.
Scheduled tasks in SQL Server
Scheduled windows tasks.
I really don't like schecduled tasks. I would rather put this function in a windows servic and throw a timer in it. With window services you can handle stop events very nicely. I do agree with everyone else, the web site is not the place for this.
Related
I got a database of subscriptions, I want to run a for every subscriptions from one time to another every x minute.
But every subscription has its own from and to time + what every x minutes its should run the function.
Its can be many subscriptions running the same time.
Maybe its should looks like a scheduled task that starting at one specific time and runs every x minute to one specific time.
I hope I describe what I want to do right, my English is not the best.
Do anyone has any idea how I building the application todo this?
You have a couple of choices here:
Use the SQL Agent and setup jobs with the required schedule (of course, this assumes you are using SQL Server).
Write a Windows Service with a timer that queries your database and executes the different tasks as needed.
You mentioned scheduled tasks, which might be another option, but that will require you to automate the setting up of new tasks as well as the actual tasks to run. Both of these are easier to do with the options I have outlined above.
I would recommend you to use System.Threading.Timer for that. To schedule a job, do the following:
new Timer(_ => DoTheJob()).Change(your_interval_in_milliseconds, Timeout.Infinite);
then when job is done, schedule next run using the same code. That would prevent running 2 instances of the same job simultaneously.
Please let me know if that does not answer your question appropriately.
You are maybe describing just what Quartz.NET can do for you. Check it out, it might be worth spending some time.
So you should write some kind of scheduler. It will take tasks from the queue and execute them... You can create a scheduler in such a way that every task for example will run in a separate thread and it would significantly improve performance!
How is this done best? I want an app that's running on a server to trigger an event every night at 03:00.
Use windows task scheduler
If you want to do this in running app code (instead of using a task scheduler), you should choose a duration to let your app sleep that's fairly long (e.g., 1 hour, or 3,600 sec). Your app loops, and as each sleep call expires, the app periodically checks how much time is left until the deadline time (03:00). Once the remaining sleep time gets below the coarse interval time, it should be reduced to a shorter interval (halved each time, or reduced to 10 sec). Continue the loop, sleeping and reducing the interval time, until the target deadline time is reached.
This prevents the loop from waking up too often (86,400 1-sec intervals is overkill), but it also prevents the app loop from overshooting the target deadline time by sleeping too long.
You could make a timer with an interval of 1 second and when the timer goes off, check if it's 3:00.
You'll need to build it in a service in order to ensure that it runs even if there's nobody logged into the machine, and then there are lots of different methods to ensure that the trigger occurs.
Consider making a System.Timers.Timer where the Interval is set to the difference between DateTime.Now and the next 3:00.
There are two basic options here.
If you're trying to do this within an existing service, you can use a Timer to trigger yourself at 3:00 each night, and run your "task".
That being said, this is typically better handled via Windows Task Scheduler. Instead of keeping the application alive 24/7, you just schedule it to run once every day at 3:00.
Edit:
If you need to work with the Task Scheduler from code (mentioned in another comment), that is also possible. The Task Scheduler provides an API for setting up individual Tasks (ITask) via the Task scheduler (ITaskScheduler).
However, given that you're working on XP Embedded, you're probably better off just using the normal system configuration capabilities, and setting up a task to run once each day. In an embedded system, you should have enough control during your deployment to do this.
Here is a simplified version of a service that we wrote that runs a timer every 60 seconds to watch a table... you could alter the timer elapse event to check the time and run it then:
Dim Timer As System.Timers.Timer
Protected Overrides Sub OnStart(ByVal args() As String)
Timer = New System.Timers.Timer(60000)
AddHandler Timer.Elapsed, AddressOf timer_Elapsed
Timer.Start()
End Sub
Protected Overrides Sub OnStop()
Timer2.Stop()
End Sub
Private Sub timer_Elapsed(ByVal pSender As Object, ByVal pargs As System.Timers.ElapsedEventArgs)
'Ensure the tick happens in the middle of the minute
If DateTime.Now.Second < 25 Then
Timer.Interval = 65000
ElseIf DateTime.Now.Second > 35 Then
Timer.Interval = 55000
ElseIf DateTime.Now.Second >= 25 And DateTime.Now.Second <= 35 Then
Timer.Interval = 60000
End If
'Logic goes here
End Sub
Obviously, if you can, use the task scheduler like everyone else here has mentioned. It is the preferred way of doing this. I just happened to have this code laying around so I thought I'd post it in case it could be helpful to you. Also, this code worked for us because we never knew when an external source was going to edit a table. Setting the interval to a correct number of milliseconds would be a much more efficient way of doing this, as pointed out by md5sum.
This answer might be a bit left field, but we often use CruiseControl.NET for some of our scheduled tasks. It's not perfect for them all, but if it's a big job that you want to run every night and other code/outcomes depend on it then it's a good choice. You can schedule it to run whenever, get emails if it worked/failed. Run other scripts/code if it did not work, clean up files you need before you start and after.
Not the perfect solution to all situation, but it is damn powerful for those that call for it. We use it for some of our big data processing jobs, and it sends us all an email if it worked/failed and will even try again 30 minutes later if it failed the first time. It gives you a nice fuzzy feeling :)
Windows task scheduler (as suggested by klausbyskov) or a SQL Server job.
EDIT:
Or if you want a dyanically assigned time, you could create a windows service that polls every 10 minutes and performs some action at the desired time(s).
Creating a windows server in C# is fairly trivial and could do this. Just make sure you've got the security and logging figured out because it can be pretty hard to tell what's going on while it is (or isn't) running.
Use System.Threading.Timer.
I'm spawning a thread in an ASP.NET application to do scheduled tasks.
It depends on what you have available to you.
Your best bet is to use a cron job, if you are on Linux/Unix/Mac OS X, a task scheduler on Windows, or launchd on newer versions of Mac OS X.
If you want to do this from within an application, you would need a loop that checks the time on a regular basis and fires off the event if it is 03:00, but this isn't ideal.
Is the program able to run via command line? If so, create a foo.bat file, and call your program command line (very simple).
Then use Task Scheduler to run the .bat file at 3 a.m. daily.
I would like to have a timer for an ASP.net application that will kick off every Sunday night and perform something (update a table in the database). However, I really don't want to write up a service that has to be deployed on the server in addition to the web application. Is there a way to accomplish this easily? Perhaps using a Global.asax file?
It seems that the best solution was to use this technique. If I had more control over the server I would probably write up a console app to take advantage of scheduled tasks.
I'm not 100% sure where you would put it, but using a System.Threading.Timer would rock this.
// In some constructor or method that runs when the app starts.
// 1st parameter is the callback to be run every iteration.
// 2nd parameter is optional parameters for the callback.
// 3rd parameter is telling the timer when to start.
// 4th parameter is telling the timer how often to run.
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerElapsed), null, new Timespan(0), new Timespan(24, 0, 0));
// The callback, no inside the method used above.
// This will run every 24 hours.
private void TimerElapsed(object o)
{
// Do stuff.
}
Initially, you'll have to determine when to start the timer the first time, or you can turn the site on at the time you want this timer running on Sunday night.
But as others said, use something other than the site to do this. It's way easy to make a Windows service to deal with this.
I would write a console app and use Scheduled Tasks to schedule it.
Try the Quartz .NET, a job scheduler for .NET enterprise application such as ASP .NET and this should serve your purpose.
I don't think a .NET application is a good solution to your problem.
IIS Recycling will recycle the process every few hours (depending on the setting) and even if you set that interval to seven days, the application pool can still be recycled for other reasons beyond your control.
I agree with jcrs3: Just write a little console app and use scheduler. You can also write a service, but if you need something quick and easy, go with the console app.
In response to your comment about Scheduled Tasks:
Another hack would be to override an event in Global.asax, an even that is called often like Application_EndRequest() and do something similar to:
protected void Application_EndRequest()
{
if (((DateTime)Application["lastTimeRun"]) < DateTime.Today)
{
Application["lastTimeRun"] = DateTime.Today;
doSomething();
}
}
This would run after the first request after the date changed, so you wouldn't be guaranteed that this would be run precisely at 3:00 AM every morning.
I've even seed cases where you would hit the site using a Scheduled Task on another computer.
How can I write a scheduler application in C# .NET?
You could also try Quartz.Net.
It all depends on your requirements:
If you have access to a database you use a table as a queue and a service to poll the queue at regular intervals.
If your application is client only (CLI) you can use the system scheduler ("Scheduled Tasks").
Lastly, if your application is only in a database (using the CLR in SQL Server 2005 for example) then you can create a SQL Server job to schedule it.
Assuming you're writing some system that needs to perform an action at a specific clock time, the following would cover the fundamental task of raising an event.
Create a System.Timer for each event to be scheduled (wrap in an object that contains the parameters for the event). Set the timer by calculating the milliseconds until the event is supposed to happen. EG:
// Set event to occur on October 1st, 2008 at 12:30pm.
DateTime eventStarts = new DateTime(2008,10,1,12,30,00);
Timer timer = new Timer((eventStarts - DateTime.Now).TotalMilliseconds);
Since you didn't go into detail, the rest would be up to you; handle the timer.Elapsed event to do what you want, and write the application as a Windows Service or standalone or whatever.
Write a windows service, there are excellent help topics on MSDN about what you need to do in order to make it installable etc.
Next, add a timer to your project. Not a Winforms timer, those don't work in Windows Services. You'll notice this when the events don't fire. Figure out what your required timer resolution is - in other words, if you have something scheduled to start at midnight, is it Ok if it starts sometime between Midnight and 12:15AM? In production you'll set your timer to fire every X minutes, where X is whatever you can afford.
Finally, when I do this I use a Switch statement and an enum to make a state machine, which has states like "Starting", "Fatal Error", "Timer Elapsed / scan for work to do", and "Working". (I divide the above X by two, since it takes two Xs to actually do work.)
That may not be the best way of doing it, but I've done it that way a couple of times now and it has worked for me.
You can try use Windows Task Scheduler API
You can also use the timer control to have the program fire of whatever event you want every X ticks, or even just one. The best solution really depends on what you're tring to accomplish though.
In my web application there is a process that queries data from all over the web, filters it, and saves it to the database. As you can imagine this process takes some time. My current solution is to increase the page timeout and give an AJAX progress bar to the user while it loads. This is a problem for two reasons - 1) it still takes to long and the user must wait 2) it sometimes still times out.
I've dabbled in threading the process and have read I should async post it to a web service ("Fire and forget").
Some references I've read:
- MSDN
- Fire and Forget
So my question is - what is the best method?
UPDATE: After the user inputs their data I would like to redirect them to the results page that incrementally updates as the process is running in the background.
To avoid excessive architecture astronomy, I often use a hidden iframe to call the long running process and stream back progress information. Coupled with something like jsProgressBarHandler, you can pretty easily create great out-of-band progress indication for longer tasks where a generic progress animation doesn't cut it.
In your specific situation, you may want to use one LongRunningProcess.aspx call per task, to avoid those page timeouts.
For example, call LongRunningProcess.aspx?taskID=1 to kick it off and then at the end of that task, emit a
document.location = "LongRunningProcess.aspx?taskID=2".
Ad nauseum.
We had a similar issue and solved it by starting the work via an asychronous web service call (which meant that the user did not have to wait for the work to finish). The web service then started a SQL Job which performed the work and periodically updated a table with the status of the work. We provided a UI which allowed the user to query the table.
I ran into this exact problem at my last job. The best way I found was to fire off an asychronous process, and notify the user when it's done (email or something else). Making them wait that long is going to be problematic because of timeouts and wasted productivity for them. Having them wait for a progress bar can give them false sense of security that they can cancel the process when they close the browser which may not be the case depending on how you set up the system.
How are you querying the remote data?
How often does it change?
Are the results something that could be cached for a period of time?
How long a period of time are we actually talking about here?
The 'best method' is likely to depend in some way on the answers to these questions...
You can create another thread and store a reference to the thread in the session or application state, depending on wether the thread can run only once per website, or once per user session.
You can then redirect the user to a page where he can monitor the threads progress. You can set the page to refresh automatically, or display a refresh button to the user.
Upon completion of the thread, you can send an email to the user.
My solution to this, has been an out of band service that does these and caches them in db.
When the person asks for something the first time, they get a bit of a wait, and then it shows up but if they refresh, its immediate, and then, because its int he db, its now part of the hourly update for the next 24 hours from the last request.
Add the job, with its relevant parameters, to a job queue table. Then, write a windows service that will pick up these jobs and process them, save the results to an appropriate location, and email the requester with a link to the results. It is also a nice touch to give some sort of a UI so the user can check the status of their job(s).
This way is much better than launching a seperate thread or increasing the timeout, especially if your application is larger and needs to scale, as you can simply add multiple servers to process jobs if necessary.