How do you set scheduled task properly in a webapplication - c#

I have the following problem.
A customer of ours has an application that is used by multiple users. Now they want to notify the users that are inactive for more than 30 days.
I'm using Spring.Quartz to solve this problem. But now this stuff is running within a windows service (which communicates with the website's database).
I was wondering if it isn't possible to use the Quartz library within the web application.
I know this works as long as the application is active, but what if the application recycles? Or is inactive for some time (ex 2 days).
Edit: Regular inactivity is possible. But the notifications should still work.
Are there other methods to do this?
Any help is welcome.
Cheers

The Windows Service approach is best in this case. You can also create a Windows Schedule, which will call your page (e.g. http://[your-site]/[yourapp]/notifyusers.aspx), which will do what is necessary. Or, if you expect the application to be visited pretty often (so you're sure that it is not just recycled), place to Application_Start of global.asax the QueueWorkingItem to start the thread, which will have something like below:
private void MyPingThread(object state)
{
ThreadExitState lstate = state as ThreadExitState;
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset);
while (true)
{
if (lstate != null)
{
if (!lstate.Active)
return;
}
handle.WaitOne(1000 * 60 * 60 * 4); // Run the task each 4 hours
//Do your work here
}
}

Just kick of a thread when the application starts (you can use the Global.asax). Wrap it in a while(true) and a try/catch, make sure you have some nice long sleeps in place even if errors occur (i.e. outside the try/catch block), and you're good to go. Probably not appropriate if you need down-to-the-second notification, but it should work for what you're doing.

I usually create a new 'Class Library' project and add it to my solution.
Then I create a new task in Task Scheduler.
I never mix scheduled jobs with website. If scheduled job is unresponsive, it may slow down or even crash your website.

Related

Background Process in web application Asp.Net [duplicate]

I need to execute an infinite while loop and want to initiate the execution in global.asax.
My question is how exactly should I do it? Should I start a new Thread or should I use Async and Task or anything else? Inside the while loop I need to do await TaskEx.Delay(5000);
How do I do this so it will not block any other processes and will not create memory leaks?
I use VS10,AsyncCTP3,MVC4
EDIT:
public void SignalRConnectionRecovery()
{
while (true)
{
Clients.SetConnectionTimeStamp(DateTime.UtcNow.ToString());
await TaskEx.Delay(5000);
}
}
All I need to do is to run this as a singleton instance globally as long as application is available.
EDIT:SOLVED
This is the final solution in Global.asax
protected void Application_Start()
{
Thread signalRConnectionRecovery = new Thread(SignalRConnectionRecovery);
signalRConnectionRecovery.IsBackground = true;
signalRConnectionRecovery.Start();
Application["SignalRConnectionRecovery"] = signalRConnectionRecovery;
}
protected void Application_End()
{
try
{
Thread signalRConnectionRecovery = (Thread)Application["SignalRConnectionRecovery"];
if (signalRConnectionRecovery != null && signalRConnectionRecovery.IsAlive)
{
signalRConnectionRecovery.Abort();
}
}
catch
{
///
}
}
I found this nice article about how to use async worker: http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx
And this:
http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6
But I think for my needs this one will be perfect:
http://forums.asp.net/t/1433665.aspx/1
ASP.NET is not designed to handle this kind of requirement. If you need something to run constantly, you would be better off creating a windows service.
Update
ASP.NET is not designed for long running tasks. It's designed to respond quickly to HTTP requests. See Cyborgx37's answer or Can I use threads to carry out long-running jobs on IIS? for a few reasons why.
Update
Now that you finally mentioned you are working with SignalR, I see that you are trying to host SignalR within ASP.NET, correct? I think you're going about this the wrong way, see the example NuGet package referenced on the project wiki. This example uses an IAsyncHttpHandler to manage tasks.
You can start a thread in your global.asax, however it will only run till your asp.net process get recycled. This will happen at least once a day, or when no one uses of your site. If the process get recycled, the only way the thread is restarted agian, is when you have a hit on your site. So the thread is not running continueuosly.
To get a continues process it is better to start a windows service.
If you do the 'In process' solution, it realy depends on what your are doing. The Thread itself will not cause you any problems in memory or deadlocks. You should add a meganism to stop your thread when the application stops. Otherwise restarting will take a long time, because it will wait for your thread to stop.
This is an old post, but as I was seraching for this, I would like to report that in .NET 4.5.2 there is a native way to do it with QueueBackgroundWorkItem.
Take a look at this post: https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/
MarianoC
It depends what you are trying to accomplish in your while loop, but in general this is the kind of situation where a Windows Service is the best answer. Installing a Windows Service is going to require that you have admin privileges on the web server.
With an infinite loop you end up with a lot of issues regard the Windows message pump. This is the thing that keeps a Windows application alive even when the application isn't "doing" anything. Without it, a program simply ends.
The problem with an infinite loop is that the application is stuck "doing" something, which prevents other applications (or threads) from "doing" their thing. There have been a few workarounds, such as the DoEvents in Windows Forms, but they all have some serious drawbacks when it comes to responsiveness and resource management. (Acceptable on a small LOB application, maybe not on a web server.) Even if the while-loop is on a separate thread, it will use up all available processing power.
Asynchronus programming is really designed more for long-running processes, such as waiting for a database to return a result or waiting for a printer to come online. In these cases, it's the external process that is taking a long time, not a while-loop.
If a Window Service is not possible, then I think your best bet is going to be setting up a separate thread with its own message pump, but it's a bit complicated. I've never done it on a web server, but you might be able to start an Application. This will provide a message pump for you and allow you to respond to Windows events, etc. The only problem is that this is going to start a Windows application (either WPF or WinForms), which may not be desirable on a web server.
What are you trying to accomplish? Is there another way you might go about it?
I found this nice article about how to use async worker, will give it a try. http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx
And this:
http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6
But I think for my needs this one will be perfect:
http://forums.asp.net/t/1433665.aspx/1

Repeatable background method

So I've been looking all over the place for a way to do this with no success.
I'm doing an MVC5 project.
I'm trying to get a method that does something particular, to run in the background of my program repeatably every 10 mins (The method gets info from other sites and puts them in the DB).
I would love some examples via links, or some directions to do it in an efficient way.
It's not a great idea to try and tie up an IIS thread like this for background work. A better option is to have a separate process do the work e.g. Windows Service. However, if you're constrained in the options you can use maybe:
Create simple console app to do the work, and set up a Windows Scheduled Task to run it at the 10 minute interval. (This assumes that you can do that in your deployment setup)
If all else fails, create a normal action method on a controller that does the task. The task will execute when the url is hit ... so hit that url every 10 minutes via a CRON job (often provided by your hosting provider).
Not your typical options, but I get the feeling they may be practical for you.
How about using a timed event.
var timer = new System.Timers.Timer(600,000);
timer.elapsed += (sender, e) => { /*fetch data*/ };

Event vs. while(true) loop

Background is the following: A Windows Service which is supposed to perform an action once per day at a given time.
I have currently implemented this by creating a timer and added the ElapsedEventHandler. The event fires every t minutes and it is then checked that we are passed the configured time. If so the action is performed and if not nothing happens.
A colleague asked me if it was not easier just to have a while(true) loop containing a sleep() and then of course the same logic for checking if we are past the time for action.
Question:
Can one say anything about the "robustness" of an event vs. a while(loop)? I am thinking of the situation where the thread "dies" so the while(true) loop exits. Is this more "likely" to happen in the one scenario vs. the other?
I'd vote for neither.
If your service just sits idle for an entire day periodically waking up (and paging code in) to see if "it's time to run", then this is a task better suited for the Windows Task Scheduler. You can programatically install a task to run every day through the task scheduler. Then your code doesn't need to be running at all unless it's time to run. (Or if your service does need to run in the background anyway, the task in the scheduler can signal your service to wake up instead of timer logic).
Both will be equally robust if you use proper error handling.
If you don't use proper error handling they will be equally brittle.
while(true)
{
...
Thread.Sleep(1000);
}
will make your service slow when responding to the standard service events like OnStop.
Besides, where do you put your while loop? In a separate thread? You will get more manual management if you use a loop too.
To summarize: use a timer.

Automatic code execution in ASP.NET

My task is to create an ASP.NET application with a piece of code which will automatically run every half an hour. This code must append a record to the file every half an hour. It should not depend on users requests(whether they happen or not).
1) I'm writing my code in Application.Start method of Global.asax file. Am I right?
2) Do I have anything to do with the hosting (IIS) settings (e.g. change permissions to write the file, etc)?
I have already tried just putting the code to write to file into a loop in Application.Start method and then just copied the project directory to the server. However, it didn't work.
You'll need to spawn another thread to have it execute without depending on users. Putting it in a loop in the Application.Start event will basically deadlock the app.
void Application_Start(...)
{
Thread thread = new Thread(CronThread);
thread.IsBackground = true;
thread.Start();
}
private void CronThread()
{
while(true)
{
Thread.Sleep( TimeSpan.FromMinutes( 30 ) );
// Do something every half hour
}
}
This would be the place to do this in an ASP.Net application (see Pauls post for more details on how you would do this), however running your task in this way has a number of drawbacks, not least of which is that your task will only start running when your application does (i.e. when the first user accesses your site) - if the ASP.net worker process stops and does not re-start your application for whathever reason then your "background task" will stop too.
This might be acceptable, however if it is not then my approach would be to either write this as a Windows Service or as a separate executable run every half hour by a scheduled task.
See this link for an example of how to create a simple windows service using C#:
Creating a Windows Service in C# (c-sharpcorner.com)
If you're forced to use ASP.NET, I'd recommend the technique found here, which uses the cache expiration to keep ASP.NET running and firing events on a timer. But there's always the danger that if your app dies, then the timer will not restart until a page is requested, starting the app.
There's really no way around it, so if you need something reliable, you'll need to do this differently, probably with a Windows service.
No, such code would not go in your Application_Start method. That method is called when the app first runs or when it resets and has nothing to do with "every half hour".
The best way to handle this, BY FAR, is to create a separate application, either on the same computer or on another computer that has access to "the file" (whatever that means). ASP.NET is not set up for timer events and any attempt to do that in ASP.NET will mostly likely affect the performance of your website.

Long running Windows Services

Folks,
I want to develop a long running windows service (it should be working without problems for months), and I wonder what is the better option here:
Use a while(true) loop in the OnStop method
Use a timer to tick each n seconds and trigger my code
Any other options ?
Thanks
Essam
I wouldn't do #1.
I'd either do #2, or I'd spin off a separate thread during OnStart that does the actual work.
Anything but #1
The services manager (or the user, if he's the one activating the controls) expects OnStart() and OnStop() to return in a timely fashion.
The way it's usually done is to start your own thread that keeps things running and ofcourse, listens to an event that might tell it to stop.
Might be worth considering a scheduled task with a short interval. Saves writing a lot of plumbing code and dealing with the peculiarities of Windows Services timers.
Don't mess with the service controller code. If the service wants to stop, you will only make matters worse by using #1. And BTW the service can always crash, in which case your while(true) won't help you a thing.
If you really want to have a "running windows service (it should be working without problems for months)", you'd better make sure your own code is properly and thoroughly tested using unit and integration tests before your run it as a service.
I would NOT recommend #1.
What I’ve done in the past for the exact same scenario/situation is create a scheduled task that runs ever N seconds, kicks off a small script that simply does these 2 things: #1 checks for “IsAlreadyRunning” flag (which is read from the database) #2 If the flag is true, then the script immediately stops end exits. If the flag is false, the script kicks off a separate process (exe) in a new thread (which utilizes a service to perform a task that can be either very short or sometimes really long, depending on the amount of records to process). This process of course sets and resets the IsAlreadyRunning flag to ensure threads do not kick off actions that overlap. I have a service that's been running for years now with this approach and I never had any problems with it. My main process utilizes a web service and bunch of other things to perform some heavy backup operations.
The System.Threading.Timer class would seem appropiate for this sort of usage.
Is it doing a
1 clean up task, or
2 waking up and looking to see if needs to run a task
If it is something like #2, then using MSMQ would be more appropriate. With MSMQ task would get done almost immediately.

Categories