Планировщик Quartz. net собирает мусор - PullRequest
0 голосов
/ 26 марта 2020

В настоящее время выполняется 12 заданий с использованием кварца. net.

Первые 10 заданий должны выполняться каждые 30 минут. Вторые 2 задания должны выполняться каждые 3 минуты.

Проблема заключается в том, что после выполнения 2 заданий, которые выполняются каждые 3 минуты. Программа перестает работать. sh окно консоли не отвечает, но приложение больше не запускает задания.

Я предполагаю, что это потому, что планировщик получил мусор. У кого-нибудь есть решение этой проблемы?

StartAsyn c:

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)));

}

GetSchedular

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();

1 Ответ

1 голос
/ 26 марта 2020

Да, вы правы. ScheduleJob просто регистрирует задание, оно не ожидает его выполнения. В какой-то момент придет сборщик мусора и освободит память, и, насколько я помню, есть финализатор, который отменяет расписание любых заданий. Поэтому вам нужно сохранить экземпляр IScheduler, на который вы планируете.

Один из вариантов - вернуть IScheduler вызывающей стороне, чтобы он мог решить, как ее сохранить:

public async Task<IScheduler> StartAsync(CancellationToken cancellationToken)
{
    ...
    ...
    return scheduler;
}

Другой способ - просто сохранить метод экземпляра в переменной-члене, чтобы класс управлял временем жизни планировщика. Основываясь на ваших комментариях, это, вероятно, лучший подход.

Поскольку ваш класс DBSyncService зарегистрирован как служба, просто добавьте переменную-член:

private IScheduler _scheduler;

И установите ее в StartAsync и это будет означать, что время жизни планировщика определяется временем жизни службы, которая в свою очередь управляется временем жизни вашего контейнера службы.

...