.NET Core Delay vs Schedule - c#

I am trying to run a Background Scheduled Task (in a Console App) after x minutes and I can easily achieve it using Task.Delay. But, what is the advantaged of using a Task Scheduler?
EDIT: BTW, I do not have any special requirements, just want to understand why one is better than the other. A Task Scheduler requires a lot of code, so why is worth the Scheduler Task?
This is an example that I am following: https://blog.maartenballiauw.be/post/2017/08/01/building-a-scheduled-cache-updater-in-aspnet-core-2.html

Task.Delay does what it says on the tin and thats about it.
The IScheduledTask/IHostedService implementation provides a couple of features.
You have a self contained class that can have dependencies injected to run the code in its own scope.
IHostedService provides a mechanism for graceful shutdown. In an ASP.NET application, the app can be recycled, you don't have a guarantee that the code you called Task.Delay(1000*60) on will execute. With IScheduledTask solution, you implement the StopAsync() method to provide a graceful cancellation of the Task. You can also configure the Host Configuration Shutdown Timeout.
Your question is regarding a console application and it appears from here as of .Net Core 2.1 the WebHost will be replaced with Generic Host and as such will no longer pertain specifically to ASP.NET.
Tangent: I have a related question ASP.Net Core 2.0 Shutdown Timeout, what issues can I expect using a very long time out of 2 min?
<- I have not had any issues in Production with a time out of 2 min.

Related

Are the benefits to using background workers in ASP.NET if there isn't app recycling?

Background: I have a simple ASP.NET Core 3.1 site. Very rarely (three or four times per week), a user might fill out a form that triggers an email to be sent.
I don't want to delay the page response while running the 'send email' operation (even though it only takes a second or two), so from everything I've read, it seems like the code that should handle the email should be a background worker/hosted service, and the Razor pages code should place the data object to be sent in a collection that gets monitored by the background service.
What I'm not fully understanding is why this is necessary in modern ASP.NET Core.
If I was doing this in a normal C# application (not ASP), I'd simply make the 'send email' method async (it's using MailKit, which has async methods), and call the async method without awaiting, allowing the the work be done on the threadpool while allowing the response thread to continue.
But existing answers and blog posts say that calling an async method without an await in ASP is dangerous, due to the fact that IIS can restart ASP processes (application pool recycling).
Yet, most things I've read say Application Recycling is an artifact of old ASP when memory leaks were common, and it's not really a thing on .Net Core. Additionally, many ASP applications aren't even hosted in IIS anymore.
Further, as far as I can tell, IHostedService/Background Worker objects aren't doing anything special - they don't seem to add any additional threading; they just look like singletons that have additional notification for environment startup and shutdown.
So:
Is calling a fire-and-forget async method in ASP.NET Core still considered poor practice, especially if the fire and forget task is short-lived? If so, why? [see edit below for clarification]
Other than notifications for shutdown, is there any reason why a background service is considered better than borrowing a managed threadpool thread (via Task.Run or QueueBackgroundWorkItem)? Wouldn't waking a background service (if it was awaiting on object to be placed in a collection) consume a pool thread in the same way?
Edit: I acknowledge that starting a task, and reporting success to the user, when there's a chance that operation could be terminated, is poor form. There's benefit to being notified of a shutdown and being able to finalize tasks.
Perhaps a better question is, does the old behavior of cycling still exist in modern ASP (on IIS or Kestrel)? Are there other reasons an orderly shutdown might be triggered (other than server shutdown/manual stop)?
I would still call it a poor practice.
The main concern here as well as in the referenced post is mainly about the promise of task completion.
Without being aware of the ghost background tasks, the runtime will not be able to notify the tasks to gracefully stop. This may or may not cause serious issues depending on the status of the tasks at the point the termination occurs.
Using fire forget task often means, your task is at the risk of having to start all over again when the process restarts. And sometimes this is not possible due to loss of context. Imagine your fire-forget task is calling another web API with parameters provided by a web request. The parameters are likely to get wiped out from memory if the process restarts.
And remember, the recycling is not always triggered by IIS / server. It could also be triggered by people. Say when your application runs into a memory leak issue, and you may want to recycle the app process every 1 hour as a temporary relief. Then you need to make sure you don't break your background tasks.
In terms of hosting - it is still possible to host ASP.Net Core applications in-process, in which the app pool gets recycled by IIS after a configured time period, or by default 29 hours.
In terms of lifetime - hosted services are types you register to DI, so DI features could be used, for example, this built-in hosted service implements IDisposable, which means proper clean up could be done upon shutting down.
Frankly, background tasks and hosted services both allow you to do fire and forget. But when you need reliability and resilience, hosted services win.
To answer the second half of your question, the app will wait for all hosted services' StopAsync methods to finish before shutting down. As long as you await your Tasks in the hosted service, this effectively means you can assume your Tasks will be allowed to finish running before the app shuts down. The app could still be force-shutdown, which in that case, nothing is guaranteed anymore.
If you need more guarantees about your background tasks, you should move them to run in a separate process. You could use something like Runly to make it easier to break out functionality into background jobs. It also makes it easy to provide real-time feedback to the user so that you are not lying to the user when you say "everything is done" while something is still running in the background.
Full disclosure: I cofounded Runly.

How should you schedule tasks in a web api .NET 5 vNext

I am in need of scheduling tasks that need to run every hour daily. I also ideally need to "fire and forget" a task, although i could handle this by creating another task to run every 5 minutes instead.
I have created a WebApi and ideally would like to run a scheduler within this, rather than having to create another application, such as a console app and then setup a windows schedule task. I see that there is a nuget package called Quartz.net that can deal with this.
Quartz sounds good to me, because code is all in one place. Plus because i will have multiple copies of this webApi running, Quartz could run for each instance.
But overall i want stablility! I have been reading sites and they say because your application pool is recycled by default every X hours, scheduling in a webApi is not a good idea.
Has anyone done this before, and which option did they go for and why?

Need to schedule a method excecution in asp .net

I am creating a web application in which I need to allow the user to schedule the excecution of a task.
I have gone through the various threads for scheduling the task but all of them are using windows service that I am not aware of. Moreover I cannot install visual studio in the server systems due to budget constraints.
Is there a way to create a method that runs a scheduler in a background thread in the asp .net application.Any code sample will be of great help.
That's not the way to go. If you need a scheduled task you should create a console application and run it using the Windows task scheduler.
You could create an application that sends an email to the user with a link to the page where the task is supposed to be done.
One thing to understand is that ASP.NET is intended to service requests from the network.
Everything in it is geared towards that. So, yes, you can run background tasks, but there are a number of caveats and gotcha's.
For instance, IIS will shut down your ASP.NET application if it does not receive any requests for some period. Also, your Application may be restarted without warning, if it detects changes to the file system. So, running code will be aborted.
That's not to say you can't work around these, but it's really not the best fit for scheduled task execution.
Your best bet would be to store the details of the task in a database, and then using either a single always-running Windows Service (really not that difficult to do, there are plenty of examples), or a console application (as suggested) scheduled manually to run regularly, to execute these tasks.
You may find that a library such as Quartz.NET may be of help scheduling/running these tasks.

Ways to perform scheduled tasks - Windows / .NET

My issue is pretty simple.
I have an application that should be executed automatically once a day. I have no prior experience with this kind of scenario (some time ago I worked with IBM Control-M but guess that it is way more complete, complex and expensive =))
I thought about two possible solutions:
Creating a Task inside Windows Task Scheduler, which would execute the application;
Implement the application as a Window Service which would run 24/7, but only would perform the needed actions depending on the current time.
Which are the advantages/disadvantages of each approach?
Is there another way to do this?
Thanks in advance.
If it only executes once a day (or so) then just do it as a regular command line app that is executed by the windows task scheduler. Task scheduler already has all of the UI necessary to determine when to kick off the program, pass in parameters and anything else related to the scheduling of the task.
The only real reason to do this type of function as a windows service is if it needs higher execution resolution than once a minute. However, the main downside to a windows service is that you would have to manage the logic for how often/when to kick it off. Another one is that the app is always running, which leaves open the possibility for leaked memory if your code has issues.
On Unix/Linux you would use a cron job schedule a task to be executed. MS Windows' version is called the Task Scheduler and it is already a service that run 24/7 and performs the needed actions depending on the time.
Create a repeating task with the Task Scheduler to run your application. Creating, installing and configuring a service application is not exactly trivial. It's a much more involved process than creating a standard Forms or command line app and you don't need to do it anyway.
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-csharp/70633/Waitable-Timer-in-C
Another library that might be of interest is Quartz.NET

Windows Service Idea?

Let me explain the scenario and what I am trying to accomplish.
Scenario:
I have a web application that collects a date (ex 07/12/2011) and a time (ex 07:45PM) and store them into database (SQL).
What I am trying to do:
At 07:45PM on 07/12/2011, I want to call a web service to run another job.
I am thinking about building a windows service that runs every 15 minutes everyday, gathers all the "pending" requests (dates and times), queues them up, and executes the requests in that order.
Please feel free to provide any other approach for this.
In the past when I have done this I use the Windows Task Scheduler to run the exe that does what I want.
For what you are wanting to do a windows service seems like overkillm, I typically just create a basic console app that does what I need. With the Task Scheduler you can specify exactly when you want to run it and you are done.
Windows Services add a (sometimes) unnecessary level of complexity to a problem like this.
I would recommend starting with a simple console application and using Windows Scheduler to run it every x minutes.
If you decide to convert to a "real" service at a later time almost all of your code should be reusable.
You could evaluate the following solutions before writing out a windows service.
http://www.firedaemon.com/ - FireDeamon provides a free version for scheduling jobs.
http://quartznet.sourceforge.net/ - An open source scheduling library, good to go for if your windows service need to support more features.
If you are working on .NET Framework 4, this link should shed some light on this issue.
I've used Quartz.Net with some success. It's a bit more flexible than you've described. Scheduling a new task is as easy as:
public static void Schedule(DateTime when, string applicationId)
{
ISchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = factory.GetScheduler();
JobDetail jobDetail = new JobDetail("Realization Job", null, typeof(CustomTask));
jobDetail.JobDataMap["applicationId"] = applicationId;
Trigger trigger = new SimpleTrigger("Custom Task Trigger", DateTime.UtcNow, null, 0, TimeSpan.Zero);
scheduler.ScheduleJob(jobDetail, trigger);
}
Note that I have a wrapper around the JobScheduler that allows it to act as a Windows service. Creating this as a Windows service allows me to have more robust error handling and does not force me to rely on the OS like the Task Scheduler does.
I've used both Windows Task Scheduler and Windows Services in different web projects, both have their merits.
Personally, I prefer using scheduled tasks. Usually, I'll have a small generic tool calling a URL in the main web application. Sort of like a web service call. The output is appended to a log file.
The benefit of this setup is that if you deploy a new version of the web application, the service is updated as well.
I'd recommend a Windows Service only if you have to perform long-running tasks or tasks that require access to unsafe resources since these don't work well with web applications.
Then again, the same sort of tasks could also be performed from a command line tool.
In practice I've found that main problem with Windows Services is the fact they run indefinitely. In a perfect world that's not a problem. In the real world however, I've seen services leaking memory (yes, .NET based services). Over time these services will start to suck up more and more resources.
A scheduled task will start a new process for each invocation, limiting the amount of damage a leaky task can do.

Categories