Automatic code execution in ASP.NET - c#

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.

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

How do you set scheduled task properly in a webapplication

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.

Thread Aborted?

Hi,
I have a ASP.NET application where I have added a Webservice that contains a "fire and forget" method. When this method is executed it will start a loop (0-99999) and for every loop it will read a xml file and save it to the database.
The problem is that this action will take a couple of hours and it usually ends with a Thread Aborted exception?
I have seen that you can increase the executionTimeout and this is how :
<httpRuntime executionTimeout="604800"/>
<compilation debug="true">
But this does not help?
I have also tried to add a thread.sleep within the loop. If I set it to 500 it will go half way and if I set <100 it will just go a couple of 1000 loops before the thread aborted exception?
How can I solve this?
Don't run the loop inside the web service. Instead, have it in a console app, a winforms app, or possibly even a windows service. Use the web service to start up the other program.
A web service is basically a web page, and asp.net web pages are not meant to host long running processes.
This article does not directly answer your question, but contains a snippet of info relevant to my answer:
http://msdn.microsoft.com/en-us/magazine/dd296718.aspx
However, when the duration of the
operation grows longer than the
typical ASP.NET session duration (20
minutes) or requires multiple actors
(as in my hiring example), ASP.NET
does not offer sufficient support. You
may recall that the ASP.NET worker
processes automatically shut down on
idle and periodically recycle
themselves. This will cause big
problems for long-running operations,
as state held within those processes
will be lost.
and the article is a good read, at any rate. It may offer ideas for you.
Not sure if this is 'the answer', but when you receive the web service call you could consider dispatching the action onto another thread. That could then run until completion. You would want to consider how you ensure that someone doesn't kick off two of these processes simultaneously though.
I have a ASP.NET application where I
have added a Webservice that contains
a "fire and forget" method. When this
method is executed it will start a
loop (0-99999) and for every loop it
will read a xml file and save it to
the database.
Lets not go into that I fhind this approach quite... hm... bad for many reasons (like a mid of the thing reset). I would queue the request, then return, and have a queue listener do the processing with transactional integrity.
Anyhow, what you CAN do is:
Queue a WorkItem for a wpool thread to pick things up.
Return immediately.
Besides that, web services and stuff like this are not a good place for hourly long running processes. Tick off a workflow, handle it separately.

How do I program a queue to launch external applications in ASP.NET?

Using C# ASP.NET I want to program a queue. I want to have X number of a process. When it finishes it should take the next item on the list and process it. I figure the most simple way is to insert and delete it from an SQL database. My problem is:
How do I start this when I add the first item? Do I launch a separate thread? AFAIK every connection to my development environment and server is its own thread? I would need to lock something launch a thread to process the list then unlock and let the thead keep going until its done? So... 1) Should I be launching threads? If so, what kind? (I haven't done any multithreading in C# yet) 2) Should I have a static mutex in my ASP.NET project? And lock it when launching threads? (are static variables still shared across ASP connections/threads correct?) Or should I not be doing this and launch them a different way?
NOTE: I may want to launch 2 processes instead of 1 and I may want to launch other processes for other things (example 2 FFmpeg + 5 ImageMagick.)
A typical ASP.NET application will actually be sharing a thread for multiple requests (although it is possible to configure it to use one thread per request). I wouldn't recommend changing it to use one thread per request though.
Also, any work being done during an ASP.NET request has to be completed by the time you finish returning your response to the client, or it will be terminated. This includes any child threads you spawn.
Your best bet here is to set up MSMQ (or perhaps even using the SQS from Amazon) and have a windows service that pulls messages off the queue and processes them. The process would look like:
First off, it sounds like what you really want is a Windows Service.
That said, if you're committed to using ASP.NET for this, the following might work:
Make a single .aspx page whose sole purpose is to process one unit of work.
Have another page (HTML will do) that uses JavaScript to asynchronously load your first page (using something like jQuery's $.load() method).
When $.load() returns, you'll know the job is complete and you can make another request to process the next job.
Optionally, you can put something into the returned page to indicate whether or not there are any remaining units of work left in the queue. This would allow you to throttle back on the client-side when there's not any work to be done.
Client-Side Example
<script type="text/javascript">
$(document).ready(function() {
processJob();
});
function processJob() {
$('#result').load("ProcessOneJob.aspx", function() {
// called when ProcessOneJob.aspx comes back
processJob();
});
}
</script>
Pros to this approach:
Relatively simple to implement
No need to deal with threads/locking
No service to install
Cons
Relies entirely on having a machine somewhere with a browser open, pointing at this page.
A brainstorm answer. I don't know if it will work.
The issue is threads get terminated when a request is finished so create a thread outside of a request in Application_Start to avoid the problem.
To keep everything organized and simple; Have a master class that acts as a utility controlling the amount of each process you would like to launch and to do the actual launching. Call the class in void Application_Start(object sender, EventArgs e) to create the initial master thread which will launch any process (or threads) you'll need. Allow it to put itself to sleep and use the utility methods to wake it up and pass messages. Then handle the rest as needed :)

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