Repeatable background method - c#

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*/ };

Related

Run stored procedure in the background while ASP.NET C# page goes to a different page

I'd like to submit my form and then let it go to another page (telling the user that they'll receive an email when it's finished) while running the stored procedure (SQL) in the background.
I don't want the user to wait 30 mins for the search to complete and then go to the other page. How can I accomplish this?
// Clicking on the Search button
protected void btnSearch_Click(object sender, EventArgs e)
{
Guid SearchGUID;
SearchGUID = Guid.NewGuid();
Hashtable htSearch = new Hashtable();
htSearch["value"] = 2;
// Run the stored procedure (takes 30 mins)
objSmart.RunSearch(htSearch);
// Redirect to the other page
Response.Redirect("Search.aspx?search=" + SearchGUID.ToString());
}
If your background task were going to take only 30~90 seconds, it could be handled with Async, the thread pool/Tasks library, or any number of other solutions. But once it starts taking several minutes, or in your case, 30+ minutes, you need a more robust out-of-process solution. ASP.NET's architecture is just not designed for long-running background threads. IIS will recycle your application pool/domain at random intervals to optimize resource usage, and while it will try its best to let your threads finish, that's not guaranteed. See Scot Hanselman's blog post on this subject for some background and suggestions.
Here are a few solutions that you could consider, depending on your application constraints:
If you're using MS SQL Server, you might be able to encapsulate the stored procedure and the completion email in a SQL Agent Job that you kick off from your web app. (You can even run .NET code in SQL Server, although it's not pretty.)
You could write a true background process to run as an EXE and be hosted in Windows Task Scheduler. Your web app can manually kick off this task, e.g. C# start a scheduled task.
You could use a third-party background tasking/queuing framework like https://www.hangfire.io/.
You need to run the method async, as mentioned here.
This will call the method then go to the next item.

Asp.Net web application database autoUpdate functionality

I created a functionality to update my web application database using data from an xml file. I want this database to be updated after ever 24hrs. My problem is I do not know where and how in the code should I call this method such that it does not have to be triggered by a button click and its executes after every 24hrs.
Please Help.
Part of the problem with background tasks in ASP.NET is that you don't have a standard application running to kick off your threads.
If you start firing off background tasks in the webapp, you can end up with inconsistent behaviour if something causes your appdomain to fail, your task can be stopped part-way, which if you're updating a DB could be a serious issue.
The most flexible way to implement this is using a seperate application running on a windows scheduled task which updates the DB for you. This separates the task from the webapp completely, but can be awkward to maintain.
It does however mean that even if your webapp is offline for whatever reason, the DB is still updated so long as the server running the task is working at the time.
If you do wish to embed the task in the webapp, something akin to cron would be preferable, as it will allow you to fire the task according to a set of rules, and leave it to its own devices.
Quartz Scheduler can achieve this, but can be fiddly to get working, and is sometimes overkill for simple tasks. It is worth learning for more involved systems which require a lot of tasks running in complex schedules, and allows the use of cron expressions.
HangFire is a different solution to the same problem, and is somewhat more simple than Quartz Scheduler, while still allowing cron configuration for tasks.
Using HangFire, the following will trigger the task at midnight every day (where UpdateDB is the method which runs the update).
RecurringJob.AddOrUpdate(() => UpdateDB(), "0 0 0 * * ?");
For your needs, HangFire is probably the quickest way to get this working.
The following will give you an overview of HangFire : http://docs.hangfire.io/en/latest/quick-start.html
HangFire is available in the NuGet archive so you can add it very quickly using the NuGet packages context menu, and documentation for timed tasks is here : http://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html
Hopefully this is enough to get you started.

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.

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.

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 :)

Categories