-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve async support on the startup path #24142
Comments
We'll put in |
Thanks for contacting us. |
6.0 |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
Thanks for contacting us. |
Please file some issues for the smaller work items. |
Thanks for contacting us. |
Surely it's better to solve this problem in I've identified these scenarios that currently have no good solutions:
I note that approaches that you might think would work... don't work:
I think we should accept that I also suggest that support be added for eagerly-executed service factories for Singletons which would be invoked when Finally, being able to pass arbitrary objects and data into Regarding async service factories, on a technical basis, rather than having
So a contrived
And for To summarize:
|
That was fixed in .NET 5 with this overload of UseStartup which lets you create the instance. Now you can use closures and ctor arguments again. If you need services passed into Startup then make another DI container because the container isn't mutable and that isn't going to change. Also the new hosting model removes some of the Program.cs/Startup.cs boilerplate so passing state in closures is possible and in a top level async main method. It makes the whole thing easier.
dotnet/runtime#43149 go add your +1. It's not happening for .NET 6 though. As for adding the bool the AddSingleton. That's a problem because it needs to be agreed upon by the other DI authors but if you can get consensus we can move forward with that design or we'll have to pick another one.
I don't know how we'd support any of this in reality. The problem with async factories is that you need async constructors to inject them into. It's viral, which means GetService would need to either block or throw. It also means that async factories can have both sync and async dependencies but sync factories can't depend on async things (or it'll be a pit of failure). This means you can't constructor inject an async service. In your example above, where does We'd also need Anyhow, thanks for the write up. Those are real concrete problems that are hard to solve. PS: it would be interested to start a discussion on async DI and see what others think. I don't know how you'd solve the constructor problem but maybe we will find some interesting solutions. EDIT: In general, you'd want to split your IO graph from your non IO graph because they have very different performance characteristics. You want to be doing all of the impure stuff on the outside, and not have IO scattered within the construction of your dependency graph. |
@davidfowl (It's 3am, what are you doing up?!)
Thanks - I've done that now. I did search around earlier but I didn't find this issue otherwise I would have done. (Can we agree GitHub search needs improvement?)
I don't think that applies. The idea being that the ...the catch being that any consumer of (In my own code, I only ever call
I would expect it to Another possibility is that given that the
When I think about it, I think this concept could be implemented without any cooperation from Something like this: ServiceCollectionExtensions:
ConfigureServices()
MyController.cs
The ASP.NET Core request plumbing would then detect if the Controller's constructor has any dependencies with async-factories and if so await them all before returning the constructed Controller by using the dynamic type approach:
Where, in my
|
I'm definitely looking forward to this. Essentially everything underlying the application startup has or is moving to async, and making the startup path that way would improve the fluidity. Things like initializing a Service Bus listener, or connecting to KeyVault can't even be done synchronously. Hoping this gets in .NET 7 |
It's not happening in .NET 7. I'm not sure its ever going to happen actually. I haven't seen or thought of any feasible proposal as yet. |
David mentioned that we need to inject async factories into constructors, thereby requiring async constructors. Why do we need to inject async factories? Jehoel suggested making the |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
@loic-sharma yes, it would mean you could never use these types of services in places where you can already inject things today (namely constructors). You would be forced into the service locator pattern whenever you wanted to use one of these services. I think that defeats one of the purposes of DI. That said, this is about async startup in ASP.NET Core, async DI is a part of it but not the only part. |
@davidfowl I've gotten many requests for this, increasing since the move to managed identity which is something that has to be fetched to pass into many services during startup, but unsure how much of that feedback makes its way all the way back to the team. I think the need for some of this support is escalating and would love to help justification here from the prod services that have pinged me directly if it helps. Very specifically, it's I'd be arguing not for Has some middle-ground like this to solve a lot of the pain for this area been considered? Or does that back us into a corner? |
Move to the new pattern where the statup class is explicitly instantiated by user code and |
var builder = WebApplication.CreateBuilder(args);
var startup = new Startup(builder.Configuration);
await startup.ConfigureServicesAsync(builder.Services);
var app = builder.Build();
await startup.ConfigureAsync(app);
app.Run(); This doesn't solve the |
Those interested in async DI, I wrote a proposal here dotnet/runtime#65656 |
I think that you want to be able to request both If your class doesn't do any async initialisation, you don't need to care. If you do, you can request a Task for everything (regardless of how it was created) and only await it when required. That means when or if a dependency changes to async construction, your code doesn't need to change to take advantage of it. For example, if you don't have any async initialisation in the second class, both classes have the same behaviour. public class SyncConstructor(TService service) {}
public class AsyncConstructor{
private AsyncConstructor(TService service) {}
[AsyncConstructor]
public static async Task<AsyncConstructor> Factory(Task<TService service>) {
// async stuff here...
return new AsyncConstructor(await service);
}
} Of course, it only makes sense to wait for potentially async objects. |
Any news on this Our use case: We have to fetch a key from the key vault to register client-side encrypted |
There are a few places where we lack async support that result in people making blocking call. These are using during application startup.
IAsyncStartupFilter
- Add IAsyncStartup and IAsyncStartupFilter to support async startup classes and filters #5897Startup
(ConfigureServicesAsync
,ConfigureAsync
)IConfiguration
initial load (keyvault requires an async call)The text was updated successfully, but these errors were encountered: