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?
Related
I am a longtime user of Azure's Application Insights, and I use the TelemetryClient's TrackTrace() and TrackException() liberally in every enterprise application I write.
One thing that has always bothered me slightly is that these methods are synchronous. Since these methods communicate with an external API, it would seem there is an ever-present risk of blocking; e.g., if the network is down/slow, or if App Insights' own API is having issues.
In such cases, it seems possible (at least in theory) that an entire application could hang. In such cases, if they ever occur, I would like my applications to continue operating despite failing to trace within a reasonable time frame.
I've done some research online, and it appears that there is no built-in way to call these methods asynchronously. Do you know of any way to accomplish this? (Or.....does the App Insights API have an under-the-hood black-box way of automatically preventing these sorts of things?)
Of course, I know I could always wrap my calls in a Task (e.g., await Task.Run(() => myTelemetryClient.TrackTrace("my message")); (or write an async extension method that does this). I could also use a timer to cancel such a request. But it would be nice if there was a more integrated way of doing this.
Can anyone enlighten me? Is this really a potential problem that I should be concerned with? Or am I merely tilting at windmills?
Update: I just now saw this, which indicates that AI does indeed handle tracking in an asynchronous manner "under the hood". But how can this be reliable, given the truism that asynchronous operations really need to be made async all the way up and down the call stack in order to be blocking-proof?
Is this really a potential problem that I should be concerned with?
No. None of the TrackABC() methods communicate with any external API or do anything which would take a long time. Track() runs all telemetry initializers, and then queues the item into an in-memory queue.
While the built-in telemetry initializers are designed to finish quickly and make no I/O or HttpCalls, if a user adds a telemetryinitializer which makes an http call or something similar, then Yes, it'll affect you Track() calls. But with normal usage of TelemetryInitializers, this should not be a concern.
If it's anything like the JS API, the tracking events are placed in a queue then dequeued and sent (possibly in batches at configurable intervals) independently of the TrackXXX methods. Enqueuing an event can be synchronous, but the sending end of the process can operated asynchronously. The queue decouples the two from one another. –
spender
I think #spender answered my question! Thanks!
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 a console service I'm currently testing. I was planning on using a timer for it to last all day, with an interval check every 30 seconds, however, it looks like alot of people don't like using timer's with a service in that fashion. Is It wise to use a timer? or is their a better method to approach it?
It's fine to have timers inside a service.
The question you should be asking yourself is whether you need your own service, or can just leverage a service that's already running timers (Task Scheduler). Or perhaps you should instead be responding to a user action.
I suspect they are trying to get you to do it using a thread based method this way, which is arguably superior as the wait method is designed to awake correctly in response the the service interface.
If you need to launch very frequently the service approach is better than a scheduled task.
I've got a windows service with only two methods - one private method DoWork(), and an exposed method which calls DoWork method. I want to achieve the following:
Windows service runs DoWork() method every 6 hours
An external program can also invoke the exposed method which calls DoWork() method. If the service is already running that method called from the service, DoWork() will again be invoked after the current method ends.
What's the best approach to this problem? Thanks!
An alternative approach would be to make use of a console application which can be scheduled by Windows task scheduler to run every 6 hours. In that case you don't waste resources to keep the Windows service running the entire time but only consume resources when needed.
For your second question: when you take the console app approach you can have it called by making use of Process.Start for example.
If the purpose of your application is only to run a specific task every six hours, you might be better off creating a command line application and creating a scheduled task that Windows runs automatically. Obviously, you could then manually start this application.
If you're still convinced you need a service (and honestly, from what I've seen so far, it sounds like you don't), you should look into using a Timer, but choose your timer carefully and read this article to get a better understanding of the timers built into .NET (Hint: Pay close attention to System.Timers.Timer).
To prevent reentry if another method tries to call DoWork() while the process is in the middle of performing its operation, look into using either a Mutex or a Semaphore.
there are benefits and drawbacks either way. my inclination with those options is to choose the windows service because it makes your deployment easier. scheduling things with the windows task scheduler is scriptable and can be automated for deployment to a new machine/environment, but it's still a little more nonstandard than just deploying and installing a windows service. you also need to make sure with task scheduler it is running under an account that can make the webservice call and that you aren't going to have problems with passwords expiring and your scheduled tasks suddenly not running. with a windows service, though, you need to have some sort of checking in place to make sure it is always running and that if it restarts that you don't lose hte state that lets it know when it should run next.
another option you could consider is using nservicebus sagas. sagas are really intended for more than just scheduling tasks (they persist state for workflow type processes that last for more than the duration of a single request/message), but they have a nice way of handling periodic or time-based processes (which is a big part of long running workflows). in that a saga can request that it get back a message from a timeout manager at a time it requests. using nservicebus is a bigger architectural question and probably well beyond the scope of what you are asking here, but sagas have become how i think about periodic processes and it comes with the added benefit of being able to manage some persistent state for your process (which may or may not be a concern) and gives you a reason to think about some architectural questions that perhaps you haven't considered before.
you can create a console application for your purpose. You can schedule the application to run every 6 hours. The console will have a default method called on application start. you can call your routine from this method. Hope this helps!!
Sometimes there is a lot that needs to be done when a given Action is called. Many times, there is more that needs to be done than what needs to be done to generate the next HTML for the user. In order to make the user have a faster experience, I want to only do what I need to do to get them their next view and send it off, but still do more things afterwards. How can I do this, multi-threading? Would I then need to worry about making sure different threads don't step on each others feet? Is there any built in functionality for this type of thing in ASP.NET MVC?
As others have mentioned, you can use a spawned thread to do this. I would take care to consider the 'criticality' of several edge cases:
If your background task encounters an error, and fails to do what the user expected to be done, do you have a mechanism of report this failure to the user?
Depending on how 'business critical' the various tasks are, using a robust/resilient message queue to store 'background tasks to be processed' will help protected against a scenario where the user requests some action, and the server responsible crashes, or is taken offline, or IIS service is restarted, etc. and the background thread never completes.
Just food for though on other issues you might need to address.
How can I do this, multi-threading?
Yes!
Would I then need to worry about making sure different threads don't step on each others feet?
This is something you need to take care of anyway, since two different ASP.NET request could arrive at the same time (from different clients) and be handled in two different worker threads simultaneously. So, any code accessing shared data needs to be coded in a thread-safe way anyway, even without your new feature.
Is there any built in functionality for this type of thing in ASP.NET MVC?
The standard .net multi-threading techniques should work just fine here (manually starting threads, or using the Task features, or using the Async CTP, ...).
It depends on what you want to do, and how reliable you need it to be. If the operaitons pending after the response was sent are OK to be lost, then .Net Async calls, ThreadPool or new Thread are all going to work just fine. If the process crashes the pending work is lost, but you already accepted that this can happen.
If the work requires any reliable guarantee, for instance the work incurs updates in the site database, then you cannot use the .Net process threading, you need to persist the request to do the work and then process this work even after a process restart (app-pool recycle as IIS so friendly calls them).
One way to do this is to use MSMQ. Other way is to use the a database table as a queue. The most reliable way is to use the database activation mechanisms, as described in Asynchronous procedure execution.
You can start a background task, then return from the action. This example is using the task Parallel Library, found in .NET 4.0:
public ActionResult DoSomething()
{
Task t = new Task(()=>DoSomethingAsynchronously());
t.Start();
return View();
}
I would use MSMQ for this kind of work. Rather than spawning threads in an ASP.NET application, I'd use an Asynchronous out of process way to do this. It's very simple and very clean.
In fact I've been using MSMQ in ASP.NET applications for a very long time and have never had any issues with this approach. Further, having a different process (that is an executable in a different app domain) do the long running work is an ideal way to handle it since your web application is no being used to do this work. So IIS, the threadpool and your web application can continue to do what they need to, while other processes handle long running tasks.
Maybe you should give it a try: Using an Asynchronous Controller in ASP.NET MVC