question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Question: Correct usage of ActivatorUtilities.CreateInstance and DI to dispose of transient services?

See original GitHub issue

Hi 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

  1. Simulated event stream to create many service instances and tasks
  2. 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:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
rynowakcommented, Feb 27, 2020

That is the case. If you want to manage when things are disposed, you can do it with scopes.

1reaction
rynowakcommented, Feb 11, 2020

It just seems like there is so much infrastructure code involved (looking at DefaultControllerActivator just for the answer to be use ServiceProvider.CreateScope(). Hence why i was hesitant to use this in the first place.

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.

  • There’s some error checking specific to controllers
  • There’s some caching that we do for controller types to improve performance

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.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found