【问题标题】:Quartz trigger based on file existence?基于文件存在的石英触发器?
【发布时间】:2014-06-30 18:32:19
【问题描述】:

我对使用 Quartz 非常陌生,我有一个关于触发器的问题。是否可以根据文件存在触发?我想让 Quartz 运行一个作业,直到找到某个文件,然后停止运行该作业并可能继续执行另一个作业。

例如,我想做这样的事情:

(1) Job1 每 60 秒检查一次给定目录中是否存在 File.txt。

(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 是一些秒数。)为什么它在这种情况下有效,但在其他情况下无效?我不能总是知道需要多少秒才能满足条件。

【问题讨论】:

  • getnextfiretime 说什么? quartz-scheduler.org/api/2.0.0/org/quartz/…
  • 我发现如果我把 Thread.Sleep(TimeSpan.FromSeconds(x));在第一行之后,它将继续执行 if 循环(其中 x 是秒数)。 getnextfiretime 为触发器返回正确的下一次触发时间。

标签: c# quartz-scheduler quartz.net


【解决方案1】:

这是什么类型的应用程序?

例如,如果这是一个 Windows 服务 - 要保持调度程序处于活动状态,以便它根据您的触发器挂起执行作业,您需要执行以下操作:

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

.. 这将进入 Windows 服务的override void OnStart(string[] args) 方法。

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 方法调用的

【讨论】:

    【解决方案2】:

    您似乎不了解此处涉及的并发和线程。

    问题如下。

    您的 MAIN 线程执行以下操作。

    1. 创建两个工作
    2. 给每个工作一个触发器
    3. 安排 Job1 开始
    4. 检查TestFileTrigger.fileExistence,如果为真,则启动 Job2(为假,因此不会运行)。

    THEN 线程池线程将启动 Job1。最有可能设置TestFileTrigger.fileExistence = true。但是主线程已经完成了它的工作。

    FIN.

    您绝不会回头检查TestFileTrigger.fileExistence 是否为真。所以它的结果是无关紧要的。您实际上是在得到结果之前检查结果。

    通过添加Thread.Sleep,您可以为 job1 提供足够的时间来完成并为您提供结果(job1 异步和并发运行,很明显您希望它同步运行)。例如,假设您告诉您的朋友 Fred 去商店买披萨并将其放在您的办公桌上(异步),然后立即转身想知道为什么您的办公桌上没有披萨。

    如果你自己去商店买了一个比萨带回家放在你的桌子上,然后从你的桌子上吃比萨。

    JobScheduler.ScheduleJob(job1, trigger1); 确实异步工作。

    您应该创建一个作业来结束第 4 步并安排它定期运行,或者使用内置的 FileScanJob 代替。

    【讨论】:

    • 我明白了。一旦满足条件,有没有办法停止工作?例如,我有: Job1 检查文件是否存在。如果是,则设置 fileExistence == true。 Job2 检查 fileExistence == true。如果是,做点什么。一旦文件存在,有没有办法让作业停止?有scheduler.DeleteJob,但我不确定我会把它放在哪里。在 Job1 和 Job2 内部?主内?如果我正确理解并发性,除非我使用Thread.Sleep,否则我无法在安排作业后放置 if 循环。但是不知道文件到达并满足停止条件需要多长时间。
    • 我不禁认为Quartz 是错误的做法。您正在尝试触发事件而不是时间表。 Quartz 是一个调度器,因此根据你的需要调整它是相当困难的。我个人会使用FileSystemWatcher
    • 是的,我同意。感谢您建议FileSystemWatcher,这似乎是一个更好的方法!我一定会尝试使用它。另一方面,JobChaining 会是一个潜在的替代方案吗?
    猜你喜欢
    • 2020-12-15
    • 1970-01-01
    • 2013-01-29
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    相关资源
    最近更新 更多