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?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With