Quartz.net 调度程序收集垃圾
Quartz.net scheduler gets garbage collected
目前有 12 个工作 运行正在使用 quartz.net。
前 10 个作业需要 运行 每 30 分钟。
第二个 2 个作业需要 运行 每 3 分钟。
问题出在每 3 分钟 运行 完成 2 个作业之后。该程序停止工作。它不会崩溃,控制台 window 仍在响应,但应用程序不再触发作业。
我认为这是因为调度程序收集了垃圾。有人对此有解决方案吗?
开始异步:
public async Task StartAsync(CancellationToken cancellationToken)
{
var scheduler = await GetScheduler();
await scheduler.Start();
await scheduler.ScheduleJob(GetAbsenceJob(), GetDefaultTrigger(nameof(AbsenceJob)));
await scheduler.ScheduleJob(GetAddressJob(), GetDefaultTrigger(nameof(AddressJob)));
await scheduler.ScheduleJob(GetCustomerJob(), GetDefaultTrigger(nameof(CustomerJob)));
await scheduler.ScheduleJob(GetDriverJob(), GetDefaultTrigger(nameof(DriverJob)));
await scheduler.ScheduleJob(GetPlanCombJob(), GetDefaultTrigger(nameof(PlanCombJob)));
await scheduler.ScheduleJob(GetPlanGroupJob(), GetDefaultTrigger(nameof(PlanGroupJob)));
await scheduler.ScheduleJob(GetSupplierJob(), GetDefaultTrigger(nameof(SupplierJob)));
await scheduler.ScheduleJob(GetTrailerJob(), GetDefaultTrigger(nameof(TrailerJob)));
await scheduler.ScheduleJob(GetTransportTypeJob(), GetDefaultTrigger(nameof(TransportTypeJob)));
await scheduler.ScheduleJob(GetVehicleJob(), GetDefaultTrigger(nameof(VehicleJob)));
await scheduler.ScheduleJob(GetImportFilesJob(), GetImportTrigger(nameof(ImportFilesJob)));
await scheduler.ScheduleJob(GetExtractFilesJob(), GetImportTrigger(nameof(ExtractFilesJob)));
}
获取计划
private static async Task<IScheduler> GetScheduler()
{
var props = new NameValueCollection {
{ "quartz.threadPool.threadCount", "20" },
{ "quartz.jobStore.misfireThreshold", "60000" },
{ "quartz.serializer.type", "binary" },
{ "quartz.scheduler.instanceName", "SynchroScheduler"},
{ "quartz.jobStore.type", "Quartz.Simpl.RAMJobStore, Quartz" },
{ "quartz.threadPool.type", "Quartz.Simpl.SimpleThreadPool, Quartz" }
};
var factory = new StdSchedulerFactory(props);
var scheduler = await factory.GetScheduler();
return scheduler;
}
编辑:
服务的启动方式:
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile(Text.Hostsettings, optional: true);
configHost.AddEnvironmentVariables(prefix: Text.Prefix);
configHost.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddJsonFile(Text.Appsettings, optional: true);
configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true);
configApp.AddEnvironmentVariables(prefix: Text.Prefix);
configApp.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services.AddLogging();
services.Configure<SynchroDbOptions>(hostContext.Configuration.GetSection("SynchoDbOptions"));
services.AddHostedService<DbSyncService>();
})
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
configLogging.AddConsole();
})
.UseConsoleLifetime()
.Build();
host.RunAsync();
是的,你是对的。 ScheduleJob
只是注册作业,并不等待它执行。在某个时候,垃圾收集器会出现并回收内存,而且我记得有一个终结器可以取消安排任何作业。因此,您需要存储要调度到的 IScheduler
实例。
一种选择是 return 将 IScheduler
发送给调用者,以便他们可以决定如何存储它:
public async Task<IScheduler> StartAsync(CancellationToken cancellationToken)
{
...
...
return scheduler;
}
另一种方法是让您的实例方法将其存储在成员变量中,并让 class 管理调度程序的生命周期。根据您的评论,这可能是最好的方法。
因为你的 class DBSyncService
被注册为服务然后添加一个成员变量:
private IScheduler _scheduler;
并在 StartAsync
中设置它,这意味着调度程序的生命周期由服务的生命周期管理,而服务的生命周期又由您的服务容器的生命周期管理。
目前有 12 个工作 运行正在使用 quartz.net。
前 10 个作业需要 运行 每 30 分钟。 第二个 2 个作业需要 运行 每 3 分钟。
问题出在每 3 分钟 运行 完成 2 个作业之后。该程序停止工作。它不会崩溃,控制台 window 仍在响应,但应用程序不再触发作业。
我认为这是因为调度程序收集了垃圾。有人对此有解决方案吗?
开始异步:
public async Task StartAsync(CancellationToken cancellationToken)
{
var scheduler = await GetScheduler();
await scheduler.Start();
await scheduler.ScheduleJob(GetAbsenceJob(), GetDefaultTrigger(nameof(AbsenceJob)));
await scheduler.ScheduleJob(GetAddressJob(), GetDefaultTrigger(nameof(AddressJob)));
await scheduler.ScheduleJob(GetCustomerJob(), GetDefaultTrigger(nameof(CustomerJob)));
await scheduler.ScheduleJob(GetDriverJob(), GetDefaultTrigger(nameof(DriverJob)));
await scheduler.ScheduleJob(GetPlanCombJob(), GetDefaultTrigger(nameof(PlanCombJob)));
await scheduler.ScheduleJob(GetPlanGroupJob(), GetDefaultTrigger(nameof(PlanGroupJob)));
await scheduler.ScheduleJob(GetSupplierJob(), GetDefaultTrigger(nameof(SupplierJob)));
await scheduler.ScheduleJob(GetTrailerJob(), GetDefaultTrigger(nameof(TrailerJob)));
await scheduler.ScheduleJob(GetTransportTypeJob(), GetDefaultTrigger(nameof(TransportTypeJob)));
await scheduler.ScheduleJob(GetVehicleJob(), GetDefaultTrigger(nameof(VehicleJob)));
await scheduler.ScheduleJob(GetImportFilesJob(), GetImportTrigger(nameof(ImportFilesJob)));
await scheduler.ScheduleJob(GetExtractFilesJob(), GetImportTrigger(nameof(ExtractFilesJob)));
}
获取计划
private static async Task<IScheduler> GetScheduler()
{
var props = new NameValueCollection {
{ "quartz.threadPool.threadCount", "20" },
{ "quartz.jobStore.misfireThreshold", "60000" },
{ "quartz.serializer.type", "binary" },
{ "quartz.scheduler.instanceName", "SynchroScheduler"},
{ "quartz.jobStore.type", "Quartz.Simpl.RAMJobStore, Quartz" },
{ "quartz.threadPool.type", "Quartz.Simpl.SimpleThreadPool, Quartz" }
};
var factory = new StdSchedulerFactory(props);
var scheduler = await factory.GetScheduler();
return scheduler;
}
编辑:
服务的启动方式:
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile(Text.Hostsettings, optional: true);
configHost.AddEnvironmentVariables(prefix: Text.Prefix);
configHost.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddJsonFile(Text.Appsettings, optional: true);
configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true);
configApp.AddEnvironmentVariables(prefix: Text.Prefix);
configApp.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services.AddLogging();
services.Configure<SynchroDbOptions>(hostContext.Configuration.GetSection("SynchoDbOptions"));
services.AddHostedService<DbSyncService>();
})
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
configLogging.AddConsole();
})
.UseConsoleLifetime()
.Build();
host.RunAsync();
是的,你是对的。 ScheduleJob
只是注册作业,并不等待它执行。在某个时候,垃圾收集器会出现并回收内存,而且我记得有一个终结器可以取消安排任何作业。因此,您需要存储要调度到的 IScheduler
实例。
一种选择是 return 将 IScheduler
发送给调用者,以便他们可以决定如何存储它:
public async Task<IScheduler> StartAsync(CancellationToken cancellationToken)
{
...
...
return scheduler;
}
另一种方法是让您的实例方法将其存储在成员变量中,并让 class 管理调度程序的生命周期。根据您的评论,这可能是最好的方法。
因为你的 class DBSyncService
被注册为服务然后添加一个成员变量:
private IScheduler _scheduler;
并在 StartAsync
中设置它,这意味着调度程序的生命周期由服务的生命周期管理,而服务的生命周期又由您的服务容器的生命周期管理。