Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Hosted Service scope when running as Azure Web Job

Working on a BackgroundService that is published to Azure as a Web Job, I noticed something strange (works fine on Azure, exception when running locally), so I tried to recreate the situation.

Program.cs:

using TestBackgroundJob;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddScoped<IDummyService, DummyService>();
        services.AddHostedService<Worker>();
    })
    .Build();

await host.RunAsync();

Worker

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public class Worker : BackgroundService
{
        private readonly ILogger<Worker> _logger;
        private readonly IDummyService _dummyService;

        public Worker(ILogger<Worker> logger, IDummyService dummyService)
        {
            _logger = logger;
            _dummyService = dummyService;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
}

Of course that when I run this local I get an exception, because I try to inject a scoped service inside Worker class, that being a HostedService, is singleton:

Cannot consume scoped service ‘TestBackgroundJob.IDummyService’ from singleton ‘Microsoft.Extensions.Hosting.IHostedService’.)’

However if I publish this as a Web Job on Azure, the code works fine. I could not found any articles that explain this. Looks like when running on Azure, the scope of Worker class is changed from singleton to scoped. Is that what really happen?

>Solution :

The Worker always has Singleton lifetime and won’t change.
But let’s see what happens when you want to create a default host (CreateDefaultBuilder method):

Default builder settings

The CreateDefaultBuilder method:

  • Sets the content root to the path returned by GetCurrentDirectory.
  • Loads host configuration from:
    • Environment variables prefixed with DOTNET_.
    • Command-line arguments.
  • Loads app configuration from:
    • appsettings.json.
    • appsettings.{Environment}.json.
    • User secrets when the app runs in the Development environment.
    • Environment variables.
    • Command-line arguments.
  • Adds the following logging providers:
    • Console
    • Debug
    • EventSource
    • EventLog (only when running on Windows)
  • Enables scope validation and dependency validation when the environment is Development.

As you can see the scope validation only happens in the Development (local) mode but when you publish it on Azure it will run in the Production mode.

So why it’s important to take care about not resolving Scope service to Singleton?

It’s all about using resources since when you use the Scope service in the Singleton then it will behave like a singleton and stay alive on the application lifetime!

It is recommended to use IServiceScopeFactory for solving your issue.

For reading more about Generic Host in .net, here is the place:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-7.0

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading