Question: Correct usage of ActivatorUtilities.CreateInstance and DI to dispose of transient services?
See original GitHub issueHi team, Im working creating an event based Short and Long running Job framework using the HostBuilder
.
I ahve a question about how to correctly use ActivatorUtilities.CreateInstance in such a way that the services instance are correctly disposed of to prevent memory leaks.
My current prototype approach is as such
- Simulated event stream to create many service instances and tasks
- Create Instance of task and dispatch them to run 3 ??
Question: When using ActivatorUtilities.CreateInstance
and IServiceProvider
what is the correct way to dispose of injected services to prevent memory leaks (merely setting reference reference to service to null doesnt work), or is there a better approach to injecting and creating instances in a similar fashion to api controller req/resp life cycle?
IService1
injected as Transient
public interface IService1 {
Task Test(int id);
}
public class Service1 : IService1 {
private readonly ILogger<Service1> _logger;
private readonly IService2 _service2;
private int _i;
public TestInterface(ILogger<Service1> logger, IService2 service2) {
_logger = logger;
_interface2 = interface2;
}
public async Task Test(int i) {
this._i = i;
_logger.LogInformation($"It Worked! { _service2.Test(i)}");
await Task.Delay(i)
}
}
IService2
injected as Transient
public interface IService2 {
string Test(int id);
}
public class Service2 : IService2 {
private string Id = string.Empty
public TestInterface2() {
Id = Guid.NewGuid().ToString();
}
public string Test(int i) {
return Id;
}
}
JobSchedulerService
public class JobSchedulerService : BackgroundService {
private readonly ILogger<JobSchedulerService > _logger;
private Dictionary<string, IService1> _tasks2 = new Dictionary<string, IService1>();
private Dictionary<string, Task> _tasks = new Dictionary<string, Task>();
protected JobSchedulerService (ILogger<JobSchedulerService > logger, IServiceProvider serviceProvider) {
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
await RunAsync(stoppingToken);
while (!stoppingToken.IsCancellationRequested) {
// 3. perform statemanagement of tasks and remove from task list when completed and clear transient services
}
}
public Task RunAsync(CancellationToken stoppingToken) {
// 1.
for (int i = 0; i < 1000000; i++) {
// 2.
var a = (IService1)ActivatorUtilities.CreateInstance(_serviceProvider, typeof(Service1));
_tasks.Add($"Worker_{i}", a.Test(i));
_tasks2.Add($"Worker_{i}", a);
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:11 (3 by maintainers)
Top Results From Across the Web
Dependency injection guidelines - .NET
Use ActivatorUtilities.CreateInstance to instantiate the instance outside of the container, while using the container for its dependencies.
Read more >ActivatorUtilities.CreateInstance giving "A suitable ...
So I am building a complex case here with inheritance and IOC, need to use ActivatorUtilities to inject instances and pass parameters... no ......
Read more >Activator utilities: activate anything! - On The Drift
ActivatorUtilities allows you to specify constructor arguments manually, lets take our previous controller and create an instance with an explicit transient ...
Read more >Disposing Injected Services (or: Using Dependency Injection ...
It's just the question when the dispose takes place. Automatic dispose of transient and scoped services happen at the end of a scope....
Read more >15 The Microsoft.Extensions.DependencyInjection DI Container
Listing 15.1 Simplest possible use of MS.DI. var services = new ServiceCollection(); services.AddTransient<SauceBéarnaise>(); ServiceProvider container ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
That is the case. If you want to manage when things are disposed, you can do it with scopes.
I wouldn’t read too much into the design of this class. There’s a few things going on that you probably don’t need.
In general the right want to manage disposable transients (your original question) is to use a scope. If you can share links to what you’re working on, then myself of @davidfowl can try to give you more specific advice.