C# Quartz удаление объекта джобы
Я использую Quartz в связке с Dependecy Injection. У меня есть несколько джоб, настроенных через RepeatForever(), требующие сервисы типа Transient от DI. Я обнаружил, что объекты моих IJob не удаляются после выполнения, и висят где-то в памяти вместе со всеми полученными сервисами из DI, из-за чего утекает память. Как заставить удаляться инстансы джоб после выполнения?
public class JobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public JobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job)
{
}
}
Ответы (1 шт):
Автор решения: Scrzii
→ Ссылка
Проблема оказалась в том, что DI не завершает по дефолту IDisposable сервисы если они объявлены в виде Transient. Поэтому нужно создавать пространство IServiceScope, создавать сервисы в нем и после этого вызывать Dispose этого самого пространства. Решил проблему так:
public class JobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly Dictionary<IJob, IServiceScope> _jobScopeMapping = new();
public JobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var scope = _serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob;
_jobScopeMapping.Add(job, scope);
return job;
}
public void ReturnJob(IJob job)
{
if (!_jobScopeMapping.TryGetValue(job, out var scope))
{
Console.WriteLine("Mapping for job does not found!"); // Ну здесь, конечно, логгер должен быть
return;
}
_jobScopeMapping.Remove(job);
scope.Dispose();
}
}