0

I've been scratching my head trying to get this to work but nothing I try seems to.

To summarise, I'm trying to:
1) register as a singleton, one of my services which is started by an IHostedService wrapper
2) have my HomeController instantiated on app startup with the above service injected

I started with the following, and attempted various versions of it to no avail:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddSingleton<IRunnerA, RunnerA>();
    services.AddSingleton<IRunnable>
    (
        services => services.GetRequiredService<IRunnerA>()
        // services => services.GetService<IRunnerA>() does not work either
    );

    services.AddSingleton<IHostedService, RunnableWrapper>(); // the IHostedService wrapper
}


While RunnableWrapper does kick off on app startup (i.e., its StartAsync is invoked), my HomeController below never gets instantiated:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private IRunnerA _runnerA;

    public HomeController
    (
        ILogger<HomeController> logger,
        IRunnerA runnerA
    )
    {
        // Never reaches here while debugging, given the above services config.
    }

Question: Why isn't my HomeController getting instantiated?

===

Further info:
Among the many things I attempted, I also tried what was suggested here: https://stackoverflow.com/a/52398431, but I still get the same behaviour.

Observations:

  1. Weirdly enough, if I remove the line services.AddSingleton<IHostedService, RunnableWrapper>();, my HomeController does get instantiated on app startup.
  2. If I return from my RunnableWrapper's public async Task StartAsync(CancellationToken cancellationToken) method without performing a long running operation inside it (which I thought was the whole point of a background service), my HomeController does get instantiated.
Ash
  • 2,021
  • 2
  • 26
  • 59

1 Answers1

0

It seems like the problem lies with starting a long running task in the IHostedService when it's registered inside ConfigureServices within Startup. For whatever reason, it appears to block ApplicationStarted.

As per this section, https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.0&tabs=visual-studio#ihostedservice-interface, I removed the line services.AddSingleton<IHostedService, RunnableWrapper>();, and updated CreateHostBuilder to the following:

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

Now things work as expected.

I'm not sure why StartAsync in the IHostedService is called before application start by default; if it has a long running task then it just seems to block.

Ash
  • 2,021
  • 2
  • 26
  • 59