Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start Background Task using ASP.Net Core Middleware

I'm attempting to run an asynchronous task when loading a page in ASP.Net Core, i.e., I want the task to run as soon as the user routes to the page but for the page to be displayed before the task has completed. It seems that with ASP.Net core you use middleware to perform such tasks. So I attempted to add the following to Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
        {

// Other configurations here
app.Use(async (context, next) =>
            {
                if (context.Request.Path.Value.Contains("PageWithAsyncTask"))
                {
                    var serviceWithAsyncTask = serviceProvider.GetService<IMyService>();
                    await serviceWithAsyncTask .DoAsync();
                }
                await next.Invoke();
            });

app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

}

The problem with the above is that there is a delay in the page loading until DoAsync has complete since we don't call next.Invoke() until DoAsync is complete. How do I correctly implement the above such that next.Invoke() is called immediately after I've got DoAsync running?

like image 214
James B Avatar asked Jun 05 '17 11:06

James B


Video Answer


2 Answers

In ASP.NET Core 2 the IHostedService is designed to run your background tasks. Register the IHostedService as Singleton and it is automatically started at startup:

implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x

asp-net-core-background-processing

like image 164
Peter Avatar answered Oct 31 '22 19:10

Peter


Since Asp.Net core 2.1 to use background tasks it is very convenient to implement IHostedService by deriving from the BackgroundService base class. Here is the sample taken from here:

public class MyServiceA : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Console.WriteLine("MyServiceA is starting.");

        stoppingToken.Register(() => Console.WriteLine("MyServiceA is stopping."));

        while (!stoppingToken.IsCancellationRequested)
        {
            Console.WriteLine("MyServiceA is doing background work.");

            await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
        }

        Console.WriteLine("MyServiceA background task is stopping.");
    }
}

Then just register it in Startup.ConfigureServices:

services.AddSingleton<IHostedService, MyServiceA>();

And as Stephen Cleary noted Asp.Net application may not be the best place for background tasks (e.g. when app is hosted in IIS it can be shut down because of app pool recycles), but for some scenarios it can be applied very well.

like image 41
AlbertK Avatar answered Oct 31 '22 19:10

AlbertK