Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of Ihostedservice in asp.net framework for background tasks

Tags:

I have a restful micro service (web api) in .net 4.6.2 and I want to call a fire and forget function each time after certain endpoints are called to do some database cleanup work. I don' want to use Task.Run and I want to have a much reliable dedicated process to do this job.

I found lot's of articles and discussions about how to use IhostedService in .net core for long running background tasks.

  1. Implement background tasks in microservices with IHostedService and the BackgroundService class
  2. ASP.NET Core background processing with IHostedService
  3. Background tasks with hosted services in ASP.NET Core

However I didn't find much information about the equivalent in .net framework. Is that IRegisteredObject? Can somebody please help me or direct me to the right resources.

Notes: We host the API as a windows service and don't use IIS

This is the first time I am asking a question here, therefore apologies if the question is not claer enough.

like image 831
Pubu Avatar asked Jul 17 '18 21:07

Pubu


People also ask

What is ASP NET MVC background worker?

Introduction. ASP.NET Boilerplate provides background jobs and workers that are used to execute some tasks in the background threads of an application.

What is background service in asp net core?

BackgroundService is a base class for implementing a long running IHostedService. ExecuteAsync(CancellationToken) is called to run the background service. The implementation returns a Task that represents the entire lifetime of the background service.

How do I stop BackgroundService in .NET Core?

The BackgroundService token source is cancelled by the StopAsync method. So to cancel the CustomService async work you have to call the StopAsync method. This cancel token provided to the ExecuteAsync method as parameter.


Video Answer


2 Answers

I guess it's a bit too late, but for someone with the same issue..

Do you know Quartz.NET and Hangfire.io ?

Maybe one of those both could be a very useful tool in your situation. I used it in many applications, and never had any issue.

For example, in Quartz.Net, you first have to create a "job" (it's the term used for this kind of background services) by creating a class implementing IJob interface:

public class HelloJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        await Console.Out.WriteLineAsync("Greetings from HelloJob!");
    }
}

Then, you have to define when you want to check that job, there are many ways (CRON for example) but we just gonna use a simple schedule here :

        StdSchedulerFactory factory = new StdSchedulerFactory();
        IScheduler scheduler = await factory.GetScheduler();

        await scheduler.Start();

        // define the job
        IJobDetail job = JobBuilder.Create<HelloJob>()
            .WithIdentity("job1", "group1")
            .Build();

        // Trigger the job to run now, and then repeat every 20 seconds
        ITrigger trigger = TriggerBuilder.Create()
            .WithIdentity("trigger1", "group1")
            .StartNow()
            .WithSimpleSchedule(x => x
                .WithIntervalInSeconds(20)
                .RepeatForever())
            .Build();

        // Tell quartz to schedule the job using our trigger, DON'T FORGET THIS ONE
        await scheduler.ScheduleJob(job, trigger);

You are in a micro services architecture based on windows service. You should be able to catch all "graceful" shutdown of your application. In these cases, you have to shutdown properly the Quartz scheduler :

await scheduler.Shutdown();

I personally really like these kinds of approach. It's reusable (you just have to schedule a new job here) and easy to get into that for any developer on your team.

I hope it will help you a bit with your issue.

like image 66
Rayyyz Avatar answered Oct 20 '22 04:10

Rayyyz


ASP.NET has a native solution for running background tasks: HostingEnvironment.QueueBackgroundWorkItem method, found on System.Web.Hosting.

It works either for synchronous or async methods. Different from using a ThreadPool, QueueBackgroundWorkItem ensures that ASP.NET runtime will delay the application shutdown in case there are any pending work items running.

From the official documentation:

Differs from a normal ThreadPool work item in that ASP.NET can keep track of how many work items registered through this API are currently running, and the ASP.NET runtime will try to delay AppDomain shutdown until these work items have finished executing. This API cannot be called outside of an ASP.NET-managed AppDomain. The provided CancellationToken will be signaled when the application is shutting down.

Here's an example of how it can be used:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Hosting;
using System.Web.Http;

namespace BackgroundWorkItemExample.Controllers
{
    public class HomeController : ApiController
    {
        [HttpPost]
        public IHttpActionResult Execute()
        {
            Debug.WriteLine("Doing something.");

            HostingEnvironment.QueueBackgroundWorkItem(ct => FireAndForgetMethodAsync());
            HostingEnvironment.QueueBackgroundWorkItem(ct => FireAndForgetMethod());
            HostingEnvironment.QueueBackgroundWorkItem(ct => FaultyFireAndForgetMethod());

            Debug.WriteLine("I don't care for that stuff running in the background. I'm out.");

            return Ok("It still returns, regardless of exceptions.");
        }

        private async Task FireAndForgetMethodAsync()
        {
            Debug.WriteLine("Started running an asynchronous background work item...");

            await Task.Delay(5000); // Pretend we are doing something for 5s

            Debug.WriteLine("Finished running that.");
        }

        private void FireAndForgetMethod()
        {
            Debug.WriteLine("Started running a background work item...");

            Thread.Sleep(5000); // Pretend we are doing something for 5s

            Debug.WriteLine("Finished running that.");
        }

        private void FaultyFireAndForgetMethod()
        {
            throw new Exception("I'm failing just to make a point.");
        }
    }
}

The output would be:

Doing something.
I don't care for that stuff running in the background. I'm out.
Started running a background work item...
Started running an asynchronous background work item...
Exception thrown: 'System.Exception' in WebApplication1.dll
An exception of type 'System.Exception' occurred in WebApplication1.dll but was not handled in user code
I'm failing just to make a point.
Finished running that.
Finished running that.
like image 22
Alan Lacerda Avatar answered Oct 20 '22 05:10

Alan Lacerda