Scheduling task in c# with failproof mechanism
Hi Team,
I need to execute a function say at 9 pm everyday. I have used Task scheduler. That is working fine. But the thing is I don't have control over it when something fails. If Something fails ,I need to retry 'n' times .
1) Should retry mechanism be a part of main code itself or as seperate job which takes all the failed items and update the status.
2) Is there any better open source libraries available than Task Scheduler.
Can anyone help please.
Thanks
4 Replies
try to take a look at this https://www.youtube.com/watch?v=73Q5EabiEHM
Nick Chapsas
YouTube
The Easiest Scheduling for Your .NET Applications
Check out my courses on Dometrain: https://dometrain.com
Get the source code: https://mailchi.mp/dometrain/73q5eabiehm
Become a Patreon and get special perks: https://www.patreon.com/nickchapsas
Hello, everybody, I'm Nick, and in this video, I will show you how you can implement easy scheduling for any type of .NET application in C#.
Give Cor...
I will post the comment I made to that video 2 weeks ago in here.
Conveniently the last few weeks I have been researching schedulers and I came across Hangfire, Quartz and Coravel. We ended up going with Coravel due to the ease of implementing, and the fact the other two are badly implemented. Sadly though, Coravel is not as good as is being advertised. For starters a lot must be paid for, including persistance, so this was already a dealbreaker for us. On top of that it's really bad with concurrency. The library has these Mutex handlers which supposedly fix it, but nothing was done with them. Secondly the project is also badly implemented just like the other two schedulers I mentioned. Overall I think it's a very bad idea to tell users to use this library in its current state, especially the free version. Considering how easy it is to make your own scheduler, perhaps a good video would be explaining how to do that.
TL;DR Coravel is not that good and you can make a scheduler yourself really easily without the limiting abstractions. Just look at what Coravel did to schedule and you can do it yourself (spoiler, it's a simple threaded timer method)
Did this myself for my apps and it works fine
If you have a static schedule that always invokes at 9pm, this is very easy. I'll post the steps.
1. Have a hosted service that starts a timer which is invoked every second.
2. The timer should either invoke a main handler to invoke the main logic, or it can also be done in the hosted service.
3. When the invokation happends, have three variables ready:
- A variable indicating a datetime when the next invokation should happen.
- A variable indicating when the next check for invokation should be checked.
- A Task as a TaskCompletionSource.
4. The invokation should check if the next invokation should happen, and to apply a proper delay in case something goes wrong it should also check if the next invokation should be checked at all. Lastly, to avoid invoking multiple times, check if the Task exists and is not completed.
5. When all these pass, set the next invokation check to happen 20 seconds in the future, or something, and set a new instance of the
TaskCompletionSource
to the Task. You can also use the task of the actual long running scheduled event if you have it, but this can throw exceptions so I prefer to use a new one instead.
6. In a try-catch, invoke your logic.
7. Whatever happends, a finally
block should complete the TaskCompletionSource
variable, indicating the scheduler is done.
8. Lastly, if the scheduler completed succesfully, set the variable indicating when the next invokation should happen to 9pm tomorrow.
Nice thing about this, your hosted system will have a Task shutdown method. You can await the TaskCompletionSource
in here until your scheduler is finished, before the application ends
Now you have a hosted event that checks every second is 9pm passed, and every 20 seconds it will attempt to invoke your code until it has completed
You can also extend this to have a non-linear retry count etc
As for setting the "next invokation" variable, initialize it at DateTime.Now.Date.AddHours(21)
for 9pm exactly. Then use DateTime.Now.Date.AddDays(1).AddHours(21)
or something like that for 9pm tomorrow
There are definitely still edge cases in this but that's a matter of implementing.
All in all, I advice against using Task scheduler libraries. Hangfire is not properly implemented in .NET and DI, and has many quirks. Quartz has no build in persistance of schedules, and works very bad with the database, and Coravel free is simple enough to do it yourself.thanks for the info, my answer is based purely on the Nick's video and I didn't look at the library myself... It's good to know it is a paid library and the free version kinda sucks
@internal ref struct FusedQyou Got it. Thanks for the detailed explaination. Will try your steps .