📜 ⬆️ ⬇️

How to run the background process in Asp.net

I needed to run the background process in ASP.NET. The question arose: how best to do this? A little googling on the SCOTT HANSELMAN blog, I found the post “ How to run Background Tasks in ASP.NET ”. The article is not very new - in 2014, but quite relevant, so I decided to translate it into Russian.

A few years ago, Phil Haack wrote a great article about the dangers of performing background tasks in ASP.NET. He identified three main risks associated with running the background process:

  1. An unhandled exception in a stream unrelated to a request can take a process.
  2. If you run a website in a web farm, then there is a chance to accidentally complete several instances of an application that could have launched several instances of the same task at the same time.
  3. The application domain in which the site is running, for various reasons, can be unloaded and remove the background task running in it.

Of course, you can write your own manager to manage background tasks. But, most likely, you will make it wrong. No one is going to challenge your developer skills. Just creating such a manager is a pretty subtle thing. And why do you need it?

There are many excellent options for running tasks in the background. And not just abstract techniques, but ready-made libraries.
')
Some ASP.NET applications can work on your own servers under IIS, some can be hosted in Azure.

There are several options for running background tasks:


You can find a large number of articles and videos online on how to use Azure tasks and how web roles work in Azure cloud services. But not many articles on how to run background tasks on your own server.

WEBBACKGROUNDER


As it is written on the site: "WebBackgrounder is a test of the concept of a web farm-compatible background task manager, which should work only with ASP.NET web applications." Its code has not changed for many years, but the NuGet package has been downloaded more than half a million times.

The project allows you to work with only one task, to manage repetitive tasks in the background while the web application is running.

This library is clearly not for all occasions. But if during the work of an ASP.NET application you need to run only one task, then WebBackgrounder is all you need.

using System; using System.Threading; using System.Threading.Tasks; namespace WebBackgrounder.DemoWeb { public class SampleJob : Job { public SampleJob(TimeSpan interval, TimeSpan timeout) : base("Sample Job", interval, timeout) { } public override Task Execute() { return new Task(() => Thread.Sleep(3000)); } } } 

Added to .NET 4.5.2 QUEUEBACKGROUNDWORKITEM


You can say that QueueBackgroundWorkItem was added in .NET 4.5.2 in response to the appearance of WebBackgrounder. This is not just an implementation of Task.Run. This is something more:

QBWI manages scheduled tasks that must be run in the background, regardless of any request. The difference with the usual ThreadPool element is that ASP.NET automatically keeps track of how many work items registered using the API are currently running, and if the application domain is turned off, the ASP.NET runtime tries to delay it, making it possible for the running background to finish. tasks.

Be aware that the ASP.NET runtime environment may delay the application domain shutdown by as little as 90 seconds, giving you the opportunity to complete tasks. Therefore, if you cannot complete the tasks in that time, then you need to use other, more reliable means.

The API is very simple - it uses “Func <CancellationToken, Task>”. Next, a small example that runs the background process from the MVC controller:

 public ActionResult SendEmail([Bind(Include = "Name,Email")] User user) { if (ModelState.IsValid) { HostingEnvironment.QueueBackgroundWorkItem(ct => SendMailAsync(user.Email)); return RedirectToAction("Index", "Home"); } return View(user); } 

FLUENTSCHEDULER


FluentScheduler is a more advanced and complex task manager with a fluent interface. With it, you can really manage the process of starting a task.

 using FluentScheduler; public class MyRegistry : Registry { public MyRegistry() { //   ITask     Schedule<MyTask>().ToRunNow().AndEvery(2).Seconds(); //       Schedule(() => Console.WriteLine("Timed Task - Will run every day at 9:15pm: " + DateTime.Now)).ToRunEvery(1).Days().At(21, 15); //     –        Schedule(() => { Console.WriteLine("Complex Action Task Starts: " + DateTime.Now); Thread.Sleep(1000); Console.WriteLine("Complex Action Task Ends: " + DateTime.Now); }).ToRunNow().AndEvery(1).Months().OnTheFirst(DayOfWeek.Monday).At(3, 0); } } 

FluentScheduler also supports IoC and can easily connect using your favorite Dependency Injection library, simply by implementing its ITaskFactory interface.

It should be noted that FluentScheduler can work with .NET Core.

You can use the JobException event of the JobManager object to handle exceptions that occur in background tasks. The event allows you to get information about the exception that occurred in the task.

 JobManager.JobException += (info) => Log.Fatal("An error just happened with a scheduled job: " + info.Exception); 

QUARTZ.NET


Quartz.NET is a version of the popular Java framework implemented in .NET. The framework is actively developing. To create a background task in Quartz, the IJob interface is used with a single Execute method, which must be implemented.

 using Quartz; using Quartz.Impl; using System; namespace ScheduledTaskExample.ScheduledTasks { public class JobScheduler { public static void Start() { IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler(); scheduler.Start(); IJobDetail job = JobBuilder.Create<MyJob>().Build(); ITrigger trigger = TriggerBuilder.Create() .WithDailyTimeIntervalSchedule (s => s.WithIntervalInHours(24) .OnEveryDay() .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(0, 0)) ) .Build(); scheduler.ScheduleJob(job, trigger); } } } 

To run the manager inside Application_Start, call JobScheduler.Start (). To get started, you can read the Schedule Actions and Quartz.NET (translation Scheduled Tasks In ASP.NET With Quartz.Net ).

The project has quite decent documentation which should be read before use (at least it is worth reviewing the Tutorials for Developing with Quartz ).

HANGFIRE


And the last one in the review, but certainly not the last in terms of functionality, the most advanced of all Hangfire. This is really a very advanced framework for background tasks in ASP.NET. Optionally, it can use Redis, SQL Server, SQL Azure, MSMQ or RabbitMQ to increase the reliability of task execution.

The Hangfire documentation is really excellent. I would like every open source project to have such documentation.

One of the most impressive features of the Hangfire is a built-in dashboard that allows you to view schedules, tasks in progress, and successful and unsuccessfully completed tasks.

Hangfire makes it easy to define tasks like "start and forget", information about which will be stored in the database:

 BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget")); 

You can delay the execution of the task:

 BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1)); 

Or run a task in CRON style

 RecurringJob.AddOrUpdate(() => Console.Write("Recurring"), Cron.Daily); 

Working with Hangfire is very convenient. Hangfire has good documentation and tutorials based on real-world examples.

Hangfire is a whole ecosystem for working with background tasks in ASP.NET applications.

Libraries are available as open source or Nuget packages.

Results (personally)


Choosing a library for myself, on the one hand, I want to have decent functionality, and on the other hand, I don’t want to use, for example, a database to store information about running tasks. Therefore, I did not even consider simple solutions like WebBackgrounder or QueueBackgroundWorkItem.

I already know that I need to run more than one process, and the processes can work for a long time (90 seconds limit on completion in QueueBackgroundWorkItem). FluentScheduler looks good, but I wanted more. Hangfire is an excellent solution, but it seems that it immediately requires the use of a database to store the task queue. Yes, and not quite there for free - there is a paid version.

In the end, I chose Quartz.NET for now: quite decent documentation, enough examples to quickly start using, as well as extensible functionality that can be added as the needs increase.

If you know other libraries to run background tasks or have experience solving similar problems - share in the comments.

Source: https://habr.com/ru/post/321502/


All Articles