how can you poll for example every 2 minutes inside a web application? I'm looking for something similar to a timer in winforms.
The poller class would be a singleton in the app (I use a container to handle lifecyles) and I'm also aware about the lifecycle of objects inside a webapp.
Web app code is not intended to run continuously for an indefinite time. It can be shut down or recycled by IIS based on various conditions multiple times an hour.
Better approach is to write a windows service or use scheduled tasks.
There are a lot of options. SignalR is a great framework to solve the polling problem that will gracefully fall back from WebSockets to Long Polling based on the support provided by the browser.
You have 2 options in JS
// easy
function run() {
// do stuff
}
setInterval(run, 120000)
// safer
function run() {
// do stuff
setTimout(run, 120000);
}
setTimout(run, 120000);
http://javascript.info/tutorial/settimeout-setinterval
set meta http-equiv refresh to the desired seconds in the .aspx page, the page will auto refresh as defined and you can update , for eg., Label.Text=DateTime.Now.Tostring(), to show the time. but as mentioned above its not always good practice to do this. for partial rendering you may rely on AJAX update panel
WebBackgrounder if you have small scale needs (this is easy to set up // minimal infrastructure).
Windows Service / Worker Role / Console App (that is executed as a periodic task) for serious work.
Related
I need to implement the following requirement for my job.
When a user starts a new application, a 5-minute timer begins.
If the user makes any edits to the application before the 5 minutes is up, the timer is canceled.
If the timer runs to completion, an email is sent to our company ("an application was created but abandoned").
The web server for this project is a .NET MVC project, though other than the Home Controller, all controllers inherit from System.Web.Http.ApiController rather than System.Web.Mvc.Controller. The front end is Angular 6.
It seems easy enough to start a 5-minute timer that will execute the "email send" method after 5 minutes. I'm stuck on how to implement the ability to cancel the timer if the user edits the application before the timer has run out. The command to start the application and any subsequent edits will come as separate queries to the API, so I don't have any state maintained from call to call.
My current idea is to create the timer via System.Timers.Timer when the application is started and store the timer in an ObjectCache under a unique ID representing that particular application. Then when the edit action is called, I can check the cache to see if a timer is stored that matches the application being edited, and if so, cancel the timer. If such a call doesn't come within 5 minutes, the timer will fire and the email be sent.
Will this work? (Both being able to access the timer to cancel it, and the timer firing as expected if not canceled?) Is there a better or more .NET-appropriate way to implement this requirement? Apologies for the vague scope of this question; I've had no luck with Google or searching SO, though my unfamiliarity with working with timers might be hindering my searches.
Thank you!
The root of your problem is architectural. You should probably give more thought to how your server-side is designed and how the client-side design and the server-side designs compliment one another. For starters, persistent state, the ability to run some background tasks, and the utilization of locking functionality (such as C#'s lock keyword) when accessing that persistent state would help in producing a more extensible and flexible design. How you design those features and how your client-side interacts with is up to you. One approach would be to have the API controller write to the persistent state, using locking to prevent concurrent writing, and then using a background task to monitor that persistent state and fire certain actions when necessary. Play around with designs and figure out what works for your needs. Good luck with your application.
I have action that returns only an JSON string with information.
To prevent users edit JS code which updates information every 2 seconds I also need an server side delay to prevent high CPU load.
How safe is it to use Task.Delay(2000) if there are (for example) 2000-5000 users doing same request at the same time? Information returned is different for each user.
Why do you think adding Task.Delay(2000) will reduce the CPU load? If you have a high CPU load at T, adding Task.Delay(2000) only postpones the high CPU load to T+2, which is totally helpless.
A quick solution is checking the submit frequency on the UI side, like on a web page, disable the submit button and enable it again after a few seconds. But this can be cheated since the front-end scripts can be modified.
A safer solution is checking the submit frequency on the server side, you record the last submit time somewhere (e.g. a static variable, the simplest), and reject invalid requests.
Task.Delay is totally safe to use since it doesn't involve creating or blocking threads or and it doesn't stall the CPU.
On the other hand, it is not going to help you, since it is still possible to do multiple requests from one machine. Delaying the execution without further checks is a useless way to throttle requests.
Beside the other answers that are correct in asp.net if the user use the asp.net session, there is an issue that you must know with that because the asp.net session is lock the entire site until the call returns.
So if you use that Delay, with session, you block all users... Please read about :
Does ASP.NET Web Forms prevent a double click submission?
Web app blocked while processing another web app on sharing same session
What perfmon counters are useful for identifying ASP.NET bottlenecks?
Replacing ASP.Net's session entirely
Trying to make Web Method Asynchronous
If it goes about Task.Delay, then yes, this is fine. Task.Delay results in a task with a timer that will continue with that task when it's done (in the callback of timer). Given the way it works, that doesn't block your thread and doesn't execute on another thread, so it seems to be fine. The number of requests you posted also doesn't sound big.
It is true, however, that my answer is more about using Task.Delay in ASP.NET MVC than in your particular scenario, which you would need to describe in details if you need more specific answer.
In C#, what is the best way to create a polling mechanism? So I have some code which can periodically do some action.
This is for web services so any UI-related solutions won't apply.
Thanks
If you are saying that you have a web service which is supposed to periodically take some action on it's own, then I think you haven't quite got the web services model. Web services are supposed to sit there (just like a web page) until something kicks it off.
Otherwise you are dealing with a very brittle situation where anything could cause it to just stop.
If you have a bit of code that needs to run on a timer, then you should investigate placing that code in a windows service (not to be confused with Web Service). That's what they are for.
"code which can periodically do some action" is called a "Timer". Search MSDN, you'll find three or four classes for the purpose, several of which are non-gui (System.Threading.Timer comes to mind).
EDIT: To whom do the changes need to be visible? If they are only visible to other consumers of the web service, then one approach is for each incoming request can check whether a periodic action is overdue and perform it. However, you shouldn't do things this way if (1) the changes need to be visible to e.g. other clients of the same database, or (2) the periodic changes need greater permissions than arbitrary incoming requests. Also, the periodic actions might be interrupted if the client cancels their request, and doing the actions might significantly delay the response to the client. For these reasons I don't recommend adding periodic processing to normal request/response processing.
Take a look at the System.Threading.Timer class. This makes periodic calls to a method you supply. These calls are made on a separate thread (a thread in the thread pool).
You'll want to use a timer.
There are a few timers in the .NET framework, including:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer
See this article for help choosing the right one: Comparing the Timer Classes in the .NET Framework Class Library
It sounds like you want a Timer, but that does not make sense to use in a Web service. It would make more sense if the timer was in a client. What clients use your web service?
Thanks in Advance for reading and answer this question.
I got button in asp 2.0 that will process something BIG. It will take sometime to finish (more than 30,000 comparison) and I want to know if the browser says that it lost the comunication with the server, the server will finish the process?
You probably want to modify your architecture so that the HTTP response is not dependent on the processing finishing within the timeout period. It sounds as if you are not going to tell the user anything based on the results of the calculation anyway based on the question. There are different methods you could use, but most involve writing a message to a queue, and then having a separate process, like a Windows Service monitor that queue and do the long running work separately.
You should not execute this button live on the site but instead spawn a thread server side.
You could use AJAX to tell the services to start the comparison and listen for the answer later on.
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.