48

I need to add a couple of await functions in ConfigureServices in Startup.cs and am running into an issue.

System.InvalidOperationException Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddMvc()' inside the call to 'IApplicationBuilder.ConfigureServices(...)' or 'IApplicationBuilder.UseMvc(...)' in the application startup code.

As seen by the code below, AddMvc & UseMvc are in their correct locations, however, I still get this error.

public async void ConfigureServices(IServiceCollection services)
{
    ...
    await manager.Initialize();
    var data = await manager.GetData();
    ...
    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
{
    ...
    app.UseMvc();
    ....
}

Is it possible to make ConfigureServices an async function?

silkfire
  • 22,873
  • 14
  • 77
  • 98
Brian Vu
  • 573
  • 1
  • 4
  • 8
  • Similar question with an actual answer that isn't just 'No!' ;-) https://stackoverflow.com/questions/56077346/asp-net-core-call-async-init-on-singleton-service – Simon_Weaver Jun 26 '19 at 21:49

1 Answers1

55

No, you can't. Doing that would result in a race condition.

Instead, consider making your operation synchronous or using .Wait()/.Result (depending on whether the async method returns data or not) to block until the asynchronous task completes.

Kévin Chalet
  • 36,739
  • 7
  • 114
  • 128
  • 40
    Can you explain why does the race condition occur? A bit more depth here with better understanding of what's executing when would be terrific. – Mavi Domates Mar 29 '19 at 10:24
  • 2
    Please add some explanation about the "race condition" – Vencovsky Aug 31 '20 at 14:53
  • 3
    @MaviDomates, @Vencovsky, the race condition occurs because the underlying code within the `ConfigureServices` of `IHostBuilder` continues to process the remainder of the host startup without awaiting your specific async implementation. This is because `ConfigureServices` accepts an `Action` delegate which returns no `Task` or anything that's awaitable. As far as the builder is concerned it has executed your method and done its job. – ColinM Sep 23 '20 at 13:42
  • Do not use `Wait()` or `Result()`. Atleast use `GetAwaiter` or `GetResult` if you feel you must. But in general it is bad practice because you risk deadlocks or starvation of the thread pool. [link](https://gsferreira.com/archive/2020/08/avoid-getawaiter-getresult-at-all-cost/) – Nulle Aug 26 '21 at 08:08
  • Pretty sure GetAwaiter() just wraps the task in an awaiter and GetResult() on the awaiter just calls the Result property which will call Wait() on the task if it isn't finished... The only real benefit is how exception propagate. GetAwaiter() isn't actually intended for you to use (ref: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.taskawaiter?view=netstandard-2.0) – Sinaesthetic Sep 10 '21 at 22:48
  • i.e. Both synchronous approaches are prone to deadlock. – Sinaesthetic Sep 10 '21 at 22:57
  • This also appears to be netcore web application/api. I'm fairly certain deadlocks are of no concern here because there's no context. – Sinaesthetic Sep 10 '21 at 23:07