Extensions: Add IAsyncDisposable support in netstandard2.1

Created on 19 Apr 2019  ·  7Comments  ·  Source: dotnet/extensions

Most helpful comment

Are there specific scenarios you have that this will unblock?

Oh yeah: as a library writer, being able to use IAsyncDisposable services and making sure they'll be correctly disposed of by .NET Framework applications.

Consider this demo:

public static class Program
{
    public static void Main(string[] args)
    {
        var services = new ServiceCollection();
        services.AddSingleton<MyService>();

        var provider = services.BuildServiceProvider();

        _ = provider.GetRequiredService<MyService>();
        provider.Dispose();
    }
}

public class MyService : IAsyncDisposable
{
    public ValueTask DisposeAsync() => default;
}

On .NET Core, it will throw an exception, as you have to use provider.DisposeAsync() as soon as you have IAsyncDisposable services:

System.InvalidOperationException : ''MyService' type only implements IAsyncDisposable. Use DisposeAsync to dispose the container.'

Once you switch to DisposeAsync(), everything will work flawlessly and MyService.DisposeAsync() will be correctly called.

On .NET Framework, you'll get no exception and MyService.DisposeAsync() will never be called (which is terrible).

By adopting this change in time for 3.0, you'd make async disposables behave consistently between .NET Framework and .NET Core.

Given that you've adopted exactly the same approach in the ASP.NET Core connections abstractions and in the SignalR client without any issue, I'm tempted to think it's a fairly safe change 😄

All 7 comments

Yep, I'll take this one. I started looking but we need to do some small infrastructure work (see https://github.com/aspnet/Extensions/pull/1431)

@davidfowl as part of this task, is there a chance you could use Microsoft.Bcl.AsyncInterfaces and backport all this async disposal love to .NET Standard 2.0? Both DI and Hosting could benefit from this ❤️

Yea that’s the plan

I see this was punted from 3.0. Would an external contribution help make it happen in time for 3.0? 😄

Just in case... here's my attempt: https://github.com/aspnet/Extensions/pull/2137

Would an external contribution help make it happen in time for 3.0?

Not really, it's not about the code to be written, it's about the risk level of the change and the impact it would have on customers. We now have a high bar for changes to 3.0, mostly just ship-blocking issues, while we stabilize to prepare for the release in September. In general, we are only taking high-impact bug fixes for 3.0.

Are there specific scenarios you have that this will unblock? We'll likely take this change in some branch because it seems like a good thing, but we need to make a decision between 3.0 and 5.0. Since there isn't much time to stabilize and get feedback now, taking a change like this is fairly high risk right now.

Are there specific scenarios you have that this will unblock?

Oh yeah: as a library writer, being able to use IAsyncDisposable services and making sure they'll be correctly disposed of by .NET Framework applications.

Consider this demo:

public static class Program
{
    public static void Main(string[] args)
    {
        var services = new ServiceCollection();
        services.AddSingleton<MyService>();

        var provider = services.BuildServiceProvider();

        _ = provider.GetRequiredService<MyService>();
        provider.Dispose();
    }
}

public class MyService : IAsyncDisposable
{
    public ValueTask DisposeAsync() => default;
}

On .NET Core, it will throw an exception, as you have to use provider.DisposeAsync() as soon as you have IAsyncDisposable services:

System.InvalidOperationException : ''MyService' type only implements IAsyncDisposable. Use DisposeAsync to dispose the container.'

Once you switch to DisposeAsync(), everything will work flawlessly and MyService.DisposeAsync() will be correctly called.

On .NET Framework, you'll get no exception and MyService.DisposeAsync() will never be called (which is terrible).

By adopting this change in time for 3.0, you'd make async disposables behave consistently between .NET Framework and .NET Core.

Given that you've adopted exactly the same approach in the ASP.NET Core connections abstractions and in the SignalR client without any issue, I'm tempted to think it's a fairly safe change 😄

Was this page helpful?
0 / 5 - 0 ratings