Кварцевый триггер на основе существования файла?

Я очень новичок в использовании Quartz, и у меня есть вопрос относительно триггеров. Можно ли запускать на основе существования файла? Я хотел бы, чтобы Quartz выполнял задание до тех пор, пока не будет найден определенный файл, затем прекратил выполнение этого задания и, возможно, перешел к другому.

Например, я хотел бы сделать что-то вроде этого:

(1) Job1 проверяет наличие файла File.txt в данном каталоге каждые 60 секунд.

(2) Если файл File.txt найден, запустите Job2. Job1 прекращает проверку существования файла.

Прямо сейчас у меня есть:

// Job definitions
var Job1 = JobBuilder.Create<TestEmail>().WithIdentity("job1", "group1").Build();
var Job2 = JobBuilder.Create<TestFileTrigger>().WithIdentity("job2", "group2").Build();

// Triggers
ITrigger trigger1 = TriggerBuilder.Create()
      .WithIdentity("trigger1", "group1").StartNow()
      .WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever())
      .Build();

ITrigger trigger2 = TriggerBuilder.Create()
      .WithIdentity("trigger2", "group2").StartNow()
      .Build();

// Schedule jobs
scheduler.ScheduleJob(Job1, trigger1);
if (TestFileTrigger.fileExistence == true) 
{
     scheduler.ScheduleJob(Job2, trigger2);
}

но похоже, что Job2 никогда не запускается.

TestEmail и TestFileTrigger просто выводят на консоль в данный момент. Логическое значение TestFileTrigger.fileExistence исходит из проверки существования файла в заданном месте (что и происходит).

Изменить: TestFileTrigger.fileExistence является логическим значением. Добавлены определения Job1/Job2, если это поможет.

Изменить: я обнаружил, что если я поставлю Thread.Sleep(TimeSpan.FromSeconds(x)); перед оператором if, оператор if будет выполняться, если условие будет выполнено. (Где x — некоторое количество секунд.) Почему это работает в этом случае, а не в другом? Я не всегда могу знать, сколько секунд потребуется для выполнения условия.


person user2424607    schedule 30.06.2014    source источник
comment
Что говорит getnextfiretime? quartz-scheduler.org/ API/2.0.0/org/кварц/   -  person SpaceBison    schedule 01.07.2014
comment
Я обнаружил, что если поставить Thread.Sleep(TimeSpan.FromSeconds(x)); после первой строки он продолжит цикл if (где x — некоторое количество секунд). getnextfiretime возвращает правильное время следующего срабатывания триггера.   -  person user2424607    schedule 01.07.2014


Ответы (2)


Похоже, вы не понимаете параллелизма и многопоточности, которые здесь задействованы.

Проблема заключается в следующем.

Ваш ОСНОВНОЙ поток делает следующее.

  1. Создайте два рабочих места
  2. Дайте каждому заданию триггер
  3. Запланировать запуск Job1
  4. Отметьте TestFileTrigger.fileExistence и, если оно истинно, запустите Job2 (если оно ложно, оно не запустится).

ТОГДА поток пула потоков запустит Job1. Скорее всего установка TestFileTrigger.fileExistence = true. Но основной поток уже завершил свою работу.

ПЛАВНИК.

Ни в коем случае вы не возвращаетесь и не проверяете, верно ли TestFileTrigger.fileExistence. Так что его результат не имеет значения. На самом деле вы проверяете результат ДО того, как получите результат.

Добавляя Thread.Sleep, вы даете заданию1 достаточно времени для завершения и получаете результат (задание1 выполняется асинхронно и одновременно, и ясно, что вы ожидали, что оно будет выполняться синхронно). Представьте, например, что вы говорите своему другу Фреду пойти в магазин, купить пиццу и положить ее на свой стол (асинхронно), а затем сразу же оборачиваетесь и удивляетесь, почему на вашем столе нет пиццы.

Синхронно было бы, если бы вы сами пошли в магазин, купили пиццу, взяли ее домой и поставили на свой стол, ПОТОМ ели пиццу со своего стола.

JobScheduler.ScheduleJob(job1, trigger1); работает асинхронно.

Вы должны создать задание для завершения шага 4 и запланировать его периодическое выполнение, ИЛИ вместо этого вы используете встроенный FileScanJob.

person Aron    schedule 02.07.2014
comment
Понимаю. Есть ли способ остановить работу после выполнения условия? Например, у меня есть: Job1 проверяет, существует ли файл. Если это так, устанавливает fileExistence == true. Job2 проверяет, если fileExistence == true. Если да, то что-то делает. Есть ли способ остановить работу после того, как файл существует? Есть scheduler.DeleteJob, но я не уверен, куда бы я его поместил. Внутри Job1 и Job2? Внутри главного? Если я правильно понимаю параллелизм, я не могу поставить цикл if после планирования заданий, если только я не использую Thread.Sleep. Но я не знаю, сколько времени пройдет, пока не прибудет файл и не будет выполнено условие остановки. - person user2424607; 02.07.2014
comment
Я не могу не думать, что Quartz это неправильный способ сделать это. Вы пытаетесь запустить событие, а не расписание. Quartz — это планировщик, поэтому адаптировать его под свои нужды довольно сложно. Лично я бы использовал FileSystemWatcher. - person Aron; 02.07.2014
comment
Да, я согласен. Спасибо, что предложили FileSystemWatcher, похоже, это гораздо лучший способ сделать это! Обязательно попробую использовать. С другой стороны, будет ли JobChaining потенциальной альтернативой? - person user2424607; 02.07.2014

Что это за тип приложения?

Если это, например, служба Windows - чтобы планировщик оставался живым, чтобы он зависал и выполнял задания в соответствии с вашими триггерами, вам нужно сделать что-то вроде:

ThreadStart start = SetupSchedules()
var thread = new Thread(start) { Name = "mysvc" }
thread.Start();

.. это войдет в метод override void OnStart(string[] args) службы Windows.

Метод SetupSchedules будет тем, что подключается к заданиям Quartz и будет выглядеть примерно так (код, который вы написали выше в OP, станет хорошим началом):

ISchedulerFactory factory = new StdSchedulerFactory();
JobScheduler = factory.GetScheduler();
JobScheduler.ScheduleJob(job1, trigger1);

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

Вам также понадобится что-то вроде этого:

private void ManageThread()
{
   var _thread = Thread.CurrentThread;
   while (!_threadMustStop) // false by default, set this to true in a 'shutdown' process
   {
       Thread.Sleep(10000);
   }
}

... который вы вызываете из своего метода SetupSchedules

person SpaceBison    schedule 02.07.2014