I'm trying to use Autofac as my service provider in a console application. Here is a minimal program to repro this:
```cs
using System.Threading.Tasks;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public class Program
{
public static async Task Main(string[] args) => await new HostBuilder()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.RunConsoleAsync();
}
````
It is causing a deadlock because their provider doesn't implement IDisposable. Unfortunately, the ConsoleLifetime locks until it is disposed, and this only happens if:
IServiceProvider implements IDisposableIServiceProvider disposes all IDisposable instances it createsAutofac opted not to implement IDisposable in the past because if the service provider is supposed to be disposed, they should have put IDisposable on it (from https://github.com/autofac/Autofac.Extensions.DependencyInjection/issues/3#issuecomment-242068640). I've opened a new issue where I hope they'll implement it (or allow me to), but I imagine this will be an issue for other DI containers.
https://github.com/aspnet/Hosting/blob/ec51afd9d0a973c2a00b37a4c4e529b48ce816bf/src/Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs#L58-L67
We could move the Set to StopAsync, but we'd risk skipping some events:
https://github.com/aspnet/Hosting/blob/ec51afd9d0a973c2a00b37a4c4e529b48ce816bf/src/Microsoft.Extensions.Hosting/Internal/Host.cs#L85-L95
Could ConsoleLifetime register for the IApplicationLifetime.ApplicationStopped token instead of (or in addition to) implementing IDisposable?
It wouldn't be much better than StopAsync, the order of event registration would still mean you'd miss some events and logs.
True, unless NotifyStopped() were moved to Dispose()
https://github.com/aspnet/Hosting/blob/ec51afd9d0a973c2a00b37a4c4e529b48ce816bf/src/Microsoft.Extensions.Hosting/Internal/Host.cs#L88
@Tratcher would you be open to me submitting a pr for these changes? Namely uses Autofac, and we'd like to use the hosting support for our microservices. While I can add my own lifetime to handle this, I'd prefer to get it usable by everybody if possible. I did a POC last night, and all the unit tests passed with these changes, but that might not be sufficient proof that this is a good change to make in general.
As a workaround, I've been able to do the following:
using System;
using System.Threading.Tasks;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public class Program
{
public static async Task Main(string[] args)
{
IDisposable container = null;
await new HostBuilder()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>((_, cb) => cb.RegisterBuildCallback(c => container = c))
.RunConsoleAsync();
container?.Dispose();
}
}
I'm not sure the side-effects are worth it. We'll get back to you.
I experienced the exact same thing as @abe545 , but I'm using SimpleInjector. His workaround fixes it for me, too.
Same issue. Thanks @abe545 for a workaround. Are Autofac developers aware of this issue?
@abe545 Are you still interested in fixing this? Seems like we should do something here.
@davidfowl it looks like they implemented a fix for this in Autofac. Still have the issue with SimpleInjector
SimpleInjector doesn't plug in as the IServiceCollection implementation AFAIK. Can you clarify what you mean?
I'm not entirely sure if this is the same issue but I have something similar when exiting a console app using StructureMap. The application doesn't exit when using CTRL+C
@abe545's workaround seems to work
See attached:
DaemonService.zip
We periodically close 'discussion' issues that have not been updated in a long period of time.
We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.
Most helpful comment
As a workaround, I've been able to do the following: