scoped services Archives - Learn Smart Coding https://blogs.learnsmartcoding.com/tag/scoped-services/ Everyone can code! Sat, 17 Oct 2020 03:39:06 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 209870635 Implement background tasks using IHostedService and access scoped service using IServiceScopeFactory https://blogs.learnsmartcoding.com/2020/10/17/implement-background-tasks-using-ihostedservice-and-access-scoped-service-using-iservicescopefactory/ https://blogs.learnsmartcoding.com/2020/10/17/implement-background-tasks-using-ihostedservice-and-access-scoped-service-using-iservicescopefactory/#comments Sat, 17 Oct 2020 03:39:06 +0000 https://karthiktechblog.com/?p=715 It is easy to implement Background tasks and scheduled work using IHostedService and the BackgroundService class. Sometimes it is required certain work to be offloaded when a Web API request is processed. That work could be accessing database records and update some information on some tables based on existing data. In this post, I’m going […]

The post Implement background tasks using IHostedService and access scoped service using IServiceScopeFactory appeared first on Learn Smart Coding.

]]>
It is easy to implement Background tasks and scheduled work using IHostedService and the BackgroundService class.

Sometimes it is required certain work to be offloaded when a Web API request is processed. That work could be accessing database records and update some information on some tables based on existing data.

In this post, I’m going to show how to Implement background tasks using IHostedService and the BackgroundService class that is suggested by the MSDN article.

Also, I will cover how to access your scoped service from this background task. This way you can access the service to talk to your database to process some information.

From NET Core 2.1 and up, you can use named IHostedService that helps you to easily implement hosted services.

We will register the hosted service that runs in the background while your web host or host is running.

You have to register the hosted services within the familiar ConfigureServices() method of the Startup class, as in the following code from a typical ASP.NET WebHost.

public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup();
            })
            .ConfigureServices(services =>
            {
                services.AddHostedService<StatusCheckerService>();
            });

Use only one way to register from these two options.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    //Other DI registrations;

    // Register Hosted Services
    services.AddHostedService<StatusCheckerService>();
    services.AddHostedService<MyHostedServiceA>();
    services.AddHostedService<MyHostedServiceB>();
    //...
}

Next is to use the Background base class (available only from dot net core 2.1)

/// 
/// Base class for implementing a long running .
/// 
public abstract class BackgroundService : IHostedService, IDisposable
{
    private Task _executingTask;
    private readonly CancellationTokenSource _stoppingCts =
       new CancellationTokenSource();

    protected abstract Task ExecuteAsync(CancellationToken stoppingToken);

    public virtual Task StartAsync(CancellationToken cancellationToken)
    {
        // Store the task we're executing
        _executingTask = ExecuteAsync(_stoppingCts.Token);

        // If the task is completed then return it,
        // this will bubble cancellation and failure to the caller
        if (_executingTask.IsCompleted)
        {
            return _executingTask;
        }

        // Otherwise it's running
        return Task.CompletedTask;
    }

    public virtual async Task StopAsync(CancellationToken cancellationToken)
    {
        // Stop called without start
        if (_executingTask == null)
        {
            return;
        }

        try
        {
            // Signal cancellation to the executing method
            _stoppingCts.Cancel();
        }
        finally
        {
            // Wait until the task completes or the stop token triggers
            await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
                                                          cancellationToken));
        }

    }

    public virtual void Dispose()
    {
        _stoppingCts.Cancel();
    }
}

When deriving from the above abstract base class, you just need to implement the ExecuteAsync() method in your own custom hosted service class as shown below.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks; 

namespace Services // your namespace where this class is placed
{
    public class StatusCheckerService: BackgroundService
    {
        private readonly ILogger<StatusCheckerService> logger; 

        public StatusCheckerService(
            ILogger<StatusCheckerService> logger,
        {          
            this.logger = logger;
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            logger.LogDebug($"StatusCheckerService is starting."); 

            stoppingToken.Register(() =>
                logger.LogDebug($"StatusCheckerService background task is stopping."));
            while (!stoppingToken.IsCancellationRequested)
            {
                
	// MyMethodOrLogic goes here. You may call any method inside this class.
 logger.LogDebug($"StatusCheckerService task doing background work.");
 
                await Task.Delay(5000, stoppingToken); // Time to pause this background logic
            } 
            logger.LogDebug($"StatusCheckerService background task is stopping.");

        }
    }
} 

For more detailed information on this topic, refer to this post from the MSDN article. My intention in this post is to show you how to access scoped service in this background task and communicate with the database.

Now, you wonder how to access Scoped Service from this background task?

Using IServiceScopeFactory Interface. A factory for creating instances of IServiceScope, which is used to create services within a scope

Complete logic to access scoped service.

 public class StatusCheckerService: BackgroundService
    {
        private readonly ILogger<StatusCheckerService> logger; 
		private readonly IServiceScopeFactory serviceScopeFactory;

        public StatusCheckerService(

            ILogger<StatusCheckerService> logger,IServiceScopeFactory serviceScopeFactory)
        {          
            this.logger = logger;
            this.serviceScopeFactory = serviceScopeFactory;
        }
 

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)

        {

            logger.LogDebug($"StatusCheckerService is starting."); 

            stoppingToken.Register(() =>
                logger.LogDebug($"StatusCheckerService background task is stopping."));
            while (!stoppingToken.IsCancellationRequested)
            {
                
		using (var scope = serviceScopeFactory.CreateScope())
                {
	// You can ask for any service here and DI will resolve it and give you back service instance
var contextService = scope.ServiceProvider.GetRequiredService<IContextService&ht;(); 
				   contextService.YourMethodOrServiceMethod(); //access dbcontext or anything thats available form your service
				}
                logger.LogDebug($"StatusCheckerService task doing background work."); 

                await Task.Delay(5000, stoppingToken); // Time to pause this background logic
            } 
            logger.LogDebug($"StatusCheckerService background task is stopping.");
        }
    }

Related Posts

Conclusion

In this post, I showed how to Implement background tasks using IHostedService and the BackgroundService class and access scoped service. That’s all from this post. If you have any questions or just want to chat with me, feel free to leave a comment below

The post Implement background tasks using IHostedService and access scoped service using IServiceScopeFactory appeared first on Learn Smart Coding.

]]>
https://blogs.learnsmartcoding.com/2020/10/17/implement-background-tasks-using-ihostedservice-and-access-scoped-service-using-iservicescopefactory/feed/ 6 715