How to do scheduled tasks in ASP.NET? - asp.net

I am coding a text based web browser game in ASP.NET. But i need a lil bit info so i decided to ask here.
When user enter any quest, lets say that quest take 10 mins to proceed. If user exits from game, how can i make my script to run automaticly and finish the quests and upgrade players power etc? I heard something like CronJob. But i dont know if it works for ASP.NET so i wanna hear any idea before i do this. Thank you for your help.

You could just add a cache item with a callback function.
public void SomeMethod() {
var onRemove = new CacheItemRemovedCallback(this.RemovedCallback);
Cache.Add("UserId_QuestId", "AnyValueYouMightNeed", null, DateTime.Now.AddMinutes(10), Cache.NoSlidingExpiration, CacheItemPriority.High, onRemove);
}
public void RemovedCallback(String key, Object value, CacheItemRemovedReason r){
// Your code here
}
The cache item has an expiration of 10 minutes, and as soon as it is removed from memory the RemovedCallback will be invoked.
Note: just to completely answer your question:
You could also use some of the frameworks available to schedule tasks in asp.net (such as Quartz.net).
Create a Console project in your solution and schedule it on the Web server (using the Windows Scheduler).
Create a Web Job project, if you are deploying your web in Azure.
But in your situation, using the cache is probably the simplest solution.

Related

For Hangfire, is there any sample code for non-simple tasks; and how should recurring tasks be handled when re-publishing?

I am considering using Hangfire https://www.hangfire.io to replace an older home-grown scheduling ASP.NET web site/app.
I have created a simple test project using Hangfire. I am able to start the project with Hangfire, submit (in code) a couple of very simple single and recurring tasks, view the dashboard, etc.
I'm looking for more suggestions for creating a little more complex code (and classes) for tasks to be scheduled, and I have a question about what happens with permanently scheduled tasks when re-publishing a Hangfire site to production.
I have read some of the documentation on the Hangfire site, reviewed the 2 tutorials, scanned the Hangfire forums, and searched StackOverflow and the web a bit. A lot of what I have seen shows you how to schedule something very simple (like Console.WriteLine), but nothing more complex. The "Highlighter" tutorial was useful, but that essentially shows how to schedule a single instance of a (slightly longer-running) task in response to an interactive user input. I understand how useful that can be, but I'm more interested in recurring tasks that are submitted and then run every day (or every hour, etc.) and don't need to be submitted again. These tasks could be for something like sending a batch of emails to users each night, batch processing some data, importing a nightly feed of external data, periodically calling a web service to perform some processing, etc.
Is there any sample code available that shows some examples like this, or any guidance on the most appropriate approach for structuring such code in an interface and class(es)?
Secondly, in my case, most of the tasks would be "permanent" (always existing as a recurring task). If I set up code to add these as recurring tasks shortly after starting the Hangfire application in production, how should I handle it when publishing updates to production (when this same initialization would run again)? Should I just call "AddOrUpdate" with the same ID and Hangfire will take care of it? Should I first call "RemoveIfExists" and then add the recurring task again? Is there some other approach that should be used?
One example would be a log janitor, which would run every weekday # 5:00PM to remove logs that are older than 5 days.
public void Schedule()
{
RecurringJob.AddOrUpdate<LogJanitor>(
"Janitor - Old Logs",
j => j.OnSchedule(null),
"0 17 * * 1,2,3,4,5",
TimeZoneInfo.FindSystemTimeZoneById("CST"));
}
Then we would handle it this way
public void OnSchedule(
PerformContext context)
{
DateTime timeStamp = DateTime.Today.AddDays(-5);
_logRepo.FindAndDelete(from: DateTime.MinValue, to: timeStamp);
}
These two methods are declared inside LogJanitor class. When our application starts, we get an instance of this class then call Schedule().

Start Process from .NET Web Application with Impersonalisation

I try to call an .exe file from a webapplication.
But I want the file called by the user that is impersonalisated by windoes authentication from the website.
Process process = new Process();
try
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = ConfigData.PVDToBudgetDBexePath;
process.StartInfo.CreateNoWindow = false;
process.Start();
log.Info("Process started by " + WindowsIdentity.GetCurrent().Name + " with ID: " + process.Id);
process.WaitForExit();
log.Info("After WaitForExit Process ID: " + process.Id);
}
catch (Exception ex)
{
log.Error("Error executing file with message " + ex.Message);
}
Both info log texts are logged correctly. There is no error occuring.
But the called Program does not do anything. No logging, no writing in Database.
The user has executable rights on the file.
When I call the same Code from Development Server it works fine.
I use .Net 4.5 and IIS 7
I found posts concerning this topic only for very old versions of .Net and IIS and that could not help me.
What am i doing wrong?
Or how can I find out whats going wrong?
many thanks,
EDIT:
To better make clear what I intend:
I have this (self made) exe file that imports Data from Excel Sheets into a Database. That needs some time. While doing this it logs its Progress whith log4net also into the database.
I want an UI (web application) were the user can trigger the import.
on this UI there is also an ajax progressbar that shows the progress of the import takten from the log table in the database.
I want maximum one instance of this import process to run in the same time. So I have a function that checks wheter the process is still running.
If so it does not allow to start another process. If not you can start it again.
private bool IsRunning(string name)
{
Process[] processlist = Process.GetProcesses();
if (Process.GetProcessesByName(name).Length > 0 )
{
return true;
}
else
{
return false;
}
}
I solved the problem now by starting the exe file via TimeScheduler.
path = filepath to the exe file
arguments = arguments to start the exe file with
using Microsoft.Win32.TaskScheduler;
using (TaskService taskService = new TaskService())
{
var taskDefinition = taskService.NewTask();
taskDefinition.RegistrationInfo.Author = WindowsIdentity.GetCurrent().Name;
taskDefinition.RegistrationInfo.Description = "Runs exe file";
var action = new ExecAction(path, arguments);
taskDefinition.Actions.Add(action);
taskService.RootFolder.RegisterTaskDefinition("NameOfTask", taskDefinition);
//get task:
var task = taskService.RootFolder.GetTasks().Where(a => a.Name == "NameOfTask").FirstOrDefault();
try
{
task.Run();
}
catch (Exception ex)
{
log.Error("Error starting task in TaskScheduler with message: " + ex.Message);
}
}
If you mean by development server the web server that is launched by Visual Studio, than this gives you a false test case since that server is launched by Visual Studio and uses your Windows account to run, while a standard configured IIS does not run under a "user" account but a very limited system account (luckily !!). Even if the user is logged in with a domain account in your website, the IIS process will not run under this account (that wouldn't make sense anyway). That is the reason why this code will not run in IIS and will run in your development server. Even if you get the exe to launch, it will run using the system account of IIS since you didn't supply any account, which is a limited account which will again run the exe different than you expected.
You will have to use impersonation, if you really want to go this way, but you will have to launch that process "impersonating" the user that is logged in in the website, asuuming that user account used to login even makes sense at that point. E.g. if it is a domain account, this might work, but if you use some other kind of authentication, like forms authentication, this has no meaning on OS level and thus you cannot use those credentials for impersonation in IIS.
In my experience, and I have done this a few times, impersonation in IIS is always a bad thing and is always creating issues, the same goes for launching command line process by the way.Luckily there is always a better/alternative solution when you think about it. Also the wait for a process to end in your code is not really a good practice. What if the process blocks? It will block website.
Luckily there is always a better/alternative solution when you think about it. A better/possible solution here is to use message queuing for example, where you just push a message to execute the task, and on the other end an application which processes the messages, which might use this command line tool then. That application can run under any user account you want, without you having to let IIS run under a different account. Later on you must of course come back to find the result of the operation, but that can be done using a callback in the background of your website. though this solution is a little bigger than what you are trying to do, it will have a better result on almost every field (responsiveness of your site, maintainability, scalability,..) the only thing where it is worse is the lines of code that you will need, but that is seldomly a valid factor to take into account
If you write the appplication for excel processing yourself, you can use a table in the DB as some kind of queue instead of using a message bus. Your web application then just needs to add rows with all necesarry info for the process in that table, the status and progress being one of them. Extend your processing application to monitor this table continuously and as soon as it detects a new record, it can then start to do the necessary task and update the db accordingly progress and status and end result). This avoids the messaging sub-system, will work equally good and will avoid you to have to launch a process with impersonation, which was the evil thing to start with.
You can modify the excel process to a windows service so that it runs continuously and starts with the system, but, if you don't want to, there are also tools to run any command line application as a windows service).
This technique would be much easier than the impersonation and allows your website to run in it's protected environment

How to add email scheduler in asp.net?

I want to configure e-mail scheduler in an Asp.net web application and I don't know how to achieve this thing. Does anybody have any idea how I can achieve this? I just want to send emails at specific time.
You can use scheduler frameworks such as Quartz.net. You can create Jobs in Quartz.net and creates triggers. Triggers kicks in the job at particular time, day, month, nightly basis etc etc. You will be using Cron scheduler to schedule your jobs (that is triggers).
I think the easiest way would be to write a good old fashioned console program which sends the emails when it runs. Then you simply use a scheduler to run it on the time(s) you want.
I use next solution.
In your Global.asax add this line to Application_Start method:
this.Application["Timer"] = new Timer(new TimerCallback(EMailProcessor.Process), null, 0, 60000);
Your EMailProcessor class may look like:
public class EMailProcessor
{
public static void Process(object state)
{
// Your code here
}
}
Hope this is what you need.
UPD: This works because the asp.net application are 'real' applications and running even there are no requests to the server.

Guidance on how to build a scheduler in ASP.NET MVC 4

I have a simple question to ask.. Does anyone know how to create a repetitive scheduler in ASP.NET MVC 4. What I'm attempting to build is an Irrigation System that I can set the days of the week and times for my system to activate each week. So the user would select the Day of the week along with the time and duration the system should run. How do I keep a running clock that triggers the system to turn on?.. Should I use a drop down list for my properties? Although it would be nice, I'm not asking for you to write an entire application for me.. A simple point in the right direction would help tremendously.. The problem with searching for the answers over the net is I really don't know what to search for.
Thank you in advance..
We are using Quartz.Net exactly for this. It is a port of Quartz for Java.
It is very powerful and it is quite easy to define new jobs (what should be done) and schedules (when to do it).
The new versions support a Cron scheduler which supports linux cron like configuration - so it is quite easy to start a job on every monday, or on every 5th of the month or for every 5 minutes on a given date. I think it's hard for scheduled tasks to beat this flexibility.
We are using the database configuration and a service on the server (this is the "running clock which activates things). Additionally a web services is used to configure the Quartz scheduler and the running service is changed through the database (this is done by Quartz.Net for you). All these things are supported nicely with it.
Some tips to start with cron triggers:
First thing would be the tutorial from http://quartznet.sourceforge.net/tutorial/lesson_1.html .
Lessons 1 - 3 show you the basic building blocks. Lesson 9 shows you the ADO job store (for db persistance).
Working with the cron trigger would work like this
ITrigger trigger = TriggerBuilder.Create().WithIdentity(id).StartNow().WithCronSchedule(cronstring).Build();
scheduler.ScheduleJob(job, trigger);
To give you an idea of the possibilites of the cron trigger this guide comes handy.
Follow this link:
http://scheduler-net.com/docs/simple_.net_application_with_scheduler.html
http://blog.scheduler-net.com/post/2012/10/29/5-Steps-to-a-Simple-Scheduler-in-ASPNET-MVC3MVC4.aspx
Scheduler for Web application ASP.NET MVC
Friend, you can create a scheduler with the help of following code
void Application_Start(object sender, EventArgs e)
{
System.Threading.Timer _timer = new System.Threading.Timer(
new TimerCallback(GetProducts));
_timer.Change(0, 51000); // here you can change the start time interval
}
static void GetProducts(Object state)
{
// do something
}
To make scheduled tasks on an independent date time server, and get detailed reports about all tasks, you can use A Trigger as a scheduling service. abilities such as pause, resume or delete sets of tasks using tags, archiving and storing all call results such as possible errors will really help developers independent of the programming language.
.Net library is also available:
//Create
ATrigger.Client.doCreate(TimeQuantity.Day(), "1", "http://www.example.com/myTask?something", tags);
Disclaimer: I was amoung ATrigger builders. It's an absolutely freeware, not commercial purpose.

IIS7 is it possible to get it to run a webpage every 5 mins?

I have IIS7.5. We currently have a weighted rating for entities on our website. Calculating the weighted rating is extremely slow, to the point loading the homepage now takes more than 10 seconds to load.
To solve this, I'd like to store the weighting in the database with each entity, and have IIS run a script every 5-10 minutes that recalculates the weightings.
How do I go about doing this? It would be easiest for me if it ran a webpage URL.
One approach is to use a Windows service for this rather than calling a web URL.
This can then run completely out-of-band in the background to perform calculations. Details on this are here:
http://msdn.microsoft.com/en-us/library/d56de412%28v=VS.100%29.aspx
A few advantages include:
Your IIS process will not be affected, so your users will see no slowdown
The service can be stopped or started independently of the Web site
However, you'll need to have reasonably full access to the server to install and run the service.
You can use a Cache entry for this, set to expire 10 minutes in the future.
When you add the item, use a callback function for the CacheItemRemovedCallback parameter - in this callback function do your database work and re-add the expiring cache entry.
Other options include:
Using one of the timer classes included in the BCL - there is a MSDN magazine article describing and comparing the different ones.
Writing a windows service to do this.
Using a scheduled task.
Windows service and schedules tasks still require you to have some way to communicate the results to IIS.
To not use client, only server to continuously call this function, you can create a thread on the server to call the function that calculates it.
A better way to start the thread or timer is in the Global.asax, like this sample:
public class Global : System.Web.HttpApplication
{
private Timer _timer;
void Application_Start(object sender, EventArgs e)
{
int period = 1000 * 60 * 10; // 10 minutes
_timer = new Timer(TimerCallback, null, 1000, period);
}
private void TimerCallback(object state)
{
// Do your stuff here
}
}
}
I have done something like this earlier and I had used windows scheduled tasks to call my script at specific intervals of time.
A simple batch file with WGET or similar, and help from Scheduled Tasks will do it.
http://www.gnu.org/software/wget/
you can try this to test this idea:
wget http://localhost/filename.ashx

Resources