Ways to implement a recurring functionality? - c#

I'd like to implement a recurring functionality to do something that activates, say, every Monday.
What are the ways of doing this programmatically in a Window Forms application that runs continuously in a server?
I'm familiar with delays but I haven't implemented delays that span for a week or month.

In my opinion your best bet is to write this functionality in a Console app and create a task on the server using Scheduled Tasks (or SQL Scheduler, or your favorite Scheduling tool) to execute it at whatever interval you need.
I don't like to see apps have "hidden" tasks in the code that execute at a specific time. Too many opportunities to fail without notification.
With a scheduling tool you can view/change the schedule without having to touch source code.
As side notes, Windows Forms apps should run on the client, not on the server.

If you're app is already running anyways, what I would do is have a periodic task that checks whether you want to do your weekly task
here's psudocode to demonstrate the logic.
if(today is Monday && i didn't do this task yet today)
{
//do monday stuff
}

Ideally you should perform this operation under windows scheduled task. It will then take care of the recoccurrance as well as timing.
If you need to do this via a winforms application, then there are two options - periodic time polling or blocking wait/sleep.
With periodic time polling, you set a time interval in which the application must run. Then in a loop check if this period has elapsed, and take action. You can set the required level of accuracy in side the loop.
With blocking wait, you sleep the running thread until it is time to execute. The only issue with this approach is if the server restarts, the application should regain it's state and resume any sleep operations. The accuracy of this approach should be within a few seconds (depending on the time drift of your server).

Related

.NET Scheduling many operations: single timer vs one timer for operation

I am developing a Windows Service application, in .NET, which executes many functions (it is a WCF service host), and one of the targets is running scheduled tasks.
I chose to create a System.Threading.Timer for every operation, with a dueTime set to the next execution and no period to avoid reentrancy.
Every time the operation ends, it changes the dueTime to match the next scheduled execution.
Most of the operations are scheduled to run every minute, not all toghether but delayed by some seconds each other.
Now, after adding a number of operations, about 30, it seems that the timers start to be inaccurate, starting the operations many seconds late, or even minutes late.
I am running the operation logic directly in the callback method of the timer, so the running thread should be the same as the timer.
Should I create a Task to run the operation instead of running it in the callback method to improve accuracy?
Or should I use a single timer with a fixed (1 second) dueTime to check which operations need to be started?
I don't like this last option because it would be more difficult to handle reentrancy..
Timers fire on a thread pool thread, so you are probably finding that as you add lots of timers that you are exhausting the thread pool.
You could increase the size of the thread pool, or alternatively ensure you have fewer timers than the thread pool size.
Firing off Tasks from the callback likely won't help - since you are going to be fighting for threads from the same thread pool. Unless you use long-running tasks.
We usually setup multiple timers to handle different actions within a single service. We set the intervals and start, stop the timer on the Service Start/Stop/Shutdown events (and have a variable indicating the status for each one, i.e. bool Stopped)
When the timer ticks over, we stop the timer, run the processing (which may take a while depending on the process, i.e. may take longer than the interval if its short.. (this code needs to be in a try--catch so it keeps going on errors)
After the code has processed, we check the Stopped variable and if its not stopped we start the timer again (this handles the reentrancy that you've mentioned and allows the code to stick to the interval as much as possible)
Timers are generally more accurate after about 100ms as far as I know, but should be close enough for what you want to do.
We have run this concept for years, and it hasn't let us down.
If you running these tasks as a sub-system of an ASP.NET app, you should also look at HangFire, which can handle background processing, eliminating the need for the windows service.
How accurate do the timers need to be? you could always use a single timer and run multiple processing threads at the same time? or queue the calls to some operations if less critical.
Ok, I came to a decision: since I am not able to easily reproduce the behavior, I chose to solve the root problem and use the Service process to only:
serve WCF requests done by clients
schedule operations (which was problematic)
Every operation that could eat CPU is executed by another process, which is controlled directly by the main process (with System.Diagnostics.Process and its events) and communicates with it through WCF.
When I start the secondary process, I pass to it the PID of the main process through command line. If the latter gets killed, the Process.Exited event fires, and I can close the child process too.
This way the main service usually doesn't use much CPU time, and is free to schedule happily without delays.
Thanks to all who gave me some advices!

Sitecore Scheduled Tasks vs Windows Task Scheduler for data migration

We need to migrate data from an external database to Sitecore periodically (every 12 or 24 hours). I would like to know whether creating a Sitecore Scheduled Task is what one can opt for in such a scenario. I would also like to know the performance impact it can have on the website.
Since I can also build an external app for this activity that doesn't rely on the IIS worker process and schedule the same using a Windows Task scheduler, I would like to know the benefits and drawbacks of both approaches.
The obvious answer to this is "it depends" but that's a cop out answer that drives me crazy when people use it.
A scheduled task in Sitecore will have access to the full Sitecore API, so if you are doing data manipulation of Sitecore items, this can be really attractive. Jobs also run on background threads, so it does have a large impact on the website, but obviously if you exhaust all of threads the worker process is configured to use, that will be an issue, but a very small outside one at best.
The drawback to a Sitecore scheduled task is they cannot be scheduled at a finite time. IOW - "run this task at 3am every day" is not possible, tasks run on an interval basis. Might sound like a trivial difference, just schedule it to run every 24 hours, but in practice the interval inevitably drifts. This is the big advantage Windows Scheduled tasks have. If most of the work you need to do is not related to Sitecore, then this be a good approach. I've seen hybrid approaches where a Windows scheduled task triggers a call to Sitecore, which uses the jobs API to kick off a background task, but it never felt that elegant.

Launching a long-running background task - from ASP.NET or a scheduled job

I have a fairly long-running process (several minutes) that I need to run roughly once a month - but not on a fixed schedule, but after a user clicks Go in a ASP.NET Webforms GUI page.
Since ASP.NET really isn't designed to handle long-running background tasks, my idea was to put this into a separate console app. But how to launch that as needed?
What happens if I use Process.Start(....) from my ASP.NET page's code-behind? I would like to avoid blocking the whole Web UI for 20 minutes or so... and also: even if it doesn't block my UI, what happens to my long-running task if the ASP.NET app pool recycles while it's still running?
Another idea was to have a frequently running job (runs every 2 minutes) check for some kind of a flag (e.g. existence of some database entries), and if needed, that job would then launch the long-running task.
But the same question: if I launch my 20-minute task from a job using Process.Start() - does that block the caller?
It seems like a bit of overkill to schedule that long running tasks five times a day since it typically is run only once a month - but at the same time, the user expects to have his results within a reasonable amount of time (less than 1 hour, if ever possible) after scheduling the process - so I cannot really just schedule it to run once at night either ...
Hangfire is what you are looking for. Best part is it comes with a built in dashboard.
You might have to write some logic on the top of it.
You can find it here.
http://hangfire.io/
First off - for several reasons - ASP.NET is imho not the solution for long-running tasks/jobs/... whatsoever.
I have had this requirement a lot of times, and always solved/separated it like:
Worker
A service with
Quartz.net (for scheduling and processing, even if you don't have a specific timestamp for execution - but the overall handling in this framework is simply superb)
a persistent job-store (to handle start/stop and completed/aborted/paused jobs)
eg ServiceStack as the interop between the two processes
Website
Simply calls some webservice-methods of the worker to enqueue/query/pause/stop/... a job. For querying jobs a call to a unified job-store might be an option (eg. db)
It might be a bit of an overkill for you though ... but this is my Swiss army knife for such scenarios.
Use the standard built-in Windows Task Scheduler like you have done, but invoke it from your web application.
Configure your task in Task Scheduler. It does not need to have a scheduled trigger. From your web application, just use Process.Start to kick it off:
SchTasks.exe /Run /TN Folder\Taskname
I have not used SchTasks.exe directly, but have used the Microsoft.Win32.TaskScheduler wrapper classes.

Scheduled tasks in one application (.Net C#)

I got a database of subscriptions, I want to run a for every subscriptions from one time to another every x minute.
But every subscription has its own from and to time + what every x minutes its should run the function.
Its can be many subscriptions running the same time.
Maybe its should looks like a scheduled task that starting at one specific time and runs every x minute to one specific time.
I hope I describe what I want to do right, my English is not the best.
Do anyone has any idea how I building the application todo this?
You have a couple of choices here:
Use the SQL Agent and setup jobs with the required schedule (of course, this assumes you are using SQL Server).
Write a Windows Service with a timer that queries your database and executes the different tasks as needed.
You mentioned scheduled tasks, which might be another option, but that will require you to automate the setting up of new tasks as well as the actual tasks to run. Both of these are easier to do with the options I have outlined above.
I would recommend you to use System.Threading.Timer for that. To schedule a job, do the following:
new Timer(_ => DoTheJob()).Change(your_interval_in_milliseconds, Timeout.Infinite);
then when job is done, schedule next run using the same code. That would prevent running 2 instances of the same job simultaneously.
Please let me know if that does not answer your question appropriately.
You are maybe describing just what Quartz.NET can do for you. Check it out, it might be worth spending some time.
So you should write some kind of scheduler. It will take tasks from the queue and execute them... You can create a scheduler in such a way that every task for example will run in a separate thread and it would significantly improve performance!

Windows service that will run every hour

I m able to build a windows service and install it.
I m curious how can i run this service every hour ? I want it to run every hour periodically.
I also need to know the hour range that it s running so that I can store it somewhere.
How can i do that?
Edit : This service will be installed on many machines, therefore, I dont want to create a scheduled task say on 100 servers.
If you want a task to run on a regular interval as opposed to constantly, you should look into using the Task Scheduler.
If you need your code to be a service, but to be "activated" every hour, the easiest approach would be to make your service a COM object and have a simple task scheduled every hour that invokes a jscript/vbscript that creates your COM object and calls simple method on it.
The alternative is to use any of the wait APIs to "waste" an hour without consuming cycles.
Note that you also have to consider some interesting design decisions that depend on what your scenario is:
how is your service going to be started if it crashes or is stopped by the user?
if you are started after more than an hour, should you run again or do you need to wait to get on the exact hourly schedule?
how do you keep track of the last "activation" time if the timezone or the day-light saving time has changed while you were not active?
does your service prevent the computer from going to sleep/hibernate on idling or when the laptop cover is closed? if not, do you need to awake the computer on the hour to get your service working on your schedule?
Some of those are taken care of by the task scheduler, so I would strongly recommend going that route vs. waiting for an hour in your code.
You could create a scheduled task that runs every hour, to either run the service or send a message to "wake it up". Then, either pass in the current time in the scheduled task request, or just have your program pick up the current time when it wakes up.
Task Scheduler Managed Wrapper can help you set this up programmatically; you can google for other resources as well.
There are a couple options.
You could sleep for an hour.
You might be better suited for a Scheduled Task, not a service.
Thread.Sleep(1000*60*60);
Thread.Sleep(TimeSpan.FromHours(1));
code more readable this way
Thread.Sleep() solution will make sure that your service will run in one hour intervals, not every hour i.e. each task will be started at 1 hour + time to run the task. Consider using a Timer within your service. This will be a more robust solution since you have a control when to run a task, monitor its progress etc. Just remember that each Timer event will be fired in a different thread and if the task takes longer than one hour to run you might have to wait for the first task to finish to avoid concurrent tasks.
Task schedulers may be a good idea but services are designed to do this. Services gets installed easily and logs things properly. All you need to do is, at start of service, you can install a system timer (System.Threading.Timer) or there is also one more timer.

Categories

Resources