Quartz Scheduler 的作业已触发,但 JobListener 未拾取事件
本文关键字:JobListener 事件 Scheduler 作业 Quartz | 更新日期: 2023-09-27 17:55:48
几天来我一直在努力使这项工作。我正在尝试使用石英调度程序在我的主窗体上触发一个事件,可以从中调用一个方法。我的主窗体上的代码如下:
void StartSchedule()
{
string AuctionTime = "0 0 0 ? * MON-FRI *";
JobKey jobkey = new JobKey("Auction", "G");
IJobDetail job = JobBuilder.Create<AuctionJob>()
.WithIdentity(jobkey)
.Build();
CronScheduleBuilder csb = CronScheduleBuilder.CronSchedule(new CronExpression(AuctionTime)).InTimeZone(TimeZoneInfo.Local);
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.WithIdentity("Auction-Trigger", "G")
.WithSchedule(csb)
.Build();
// Create listener
JobListener auctionListener = new JobListener();
auctionListener.JobExecutedHandler += new EventHandler(SendAuctionOrders);
IMatcher<JobKey> matcher = KeyMatcher<JobKey>.KeyEquals(jobkey);
_scheduler.ListenerManager.AddJobListener(auctionlistener, matcher);
// Add to scheduler
DateTimeOffset ft = _scheduler.ScheduleJob(job, trigger);
LogEvent(job.Key + " scheduled at: " + ft.ToLocalTime());
jobkey = new JobKey("Auction2", "G");
IJobDetail job = JobBuilder.Create<AuctionJob>()
.WithIdentity(jobkey)
.Build();
csb = CronScheduleBuilder.CronSchedule(new CronExpression(AuctionTime)).InTimeZone(TimeZoneInfo.Local);
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.WithIdentity("Auction-Trigger", "G")
.WithSchedule(csb)
.Build();
// Create listener
JobListener auction2Listener = new JobListener();
auction2Listener.JobExecutedHandler += new EventHandler(SendAuctionOrders);
IMatcher<JobKey> matcher = KeyMatcher<JobKey>.KeyEquals(jobkey);
_scheduler.ListenerManager.AddJobListener(auction2listener, matcher);
// Add to scheduler
ft = _scheduler.ScheduleJob(job, trigger);
LogEvent(job.Key + " scheduled at: " + ft.ToLocalTime());
_scheduler.Start();
}
void SendAuctionOrders()
{
// Do something
}
AuctionJob 类如下所示:
public class AuctionJob : IJob
{
public void Execute(IJobExecutionContext context)
{
// Empty
Console.WriteLine("auction exec");
}
}
而作业侦听器如下所示:
public class JobListener : IJobListener
{
private static readonly ILog logger = LogManager.GetLogger(typeof(JobListener));
public event EventHandler JobExecutedHandler;
public void JobExecutionVetoed(IJobExecutionContext context)
{
logger.Info("JobExecutionVetoed");
}
public void JobToBeExecuted(IJobExecutionContext context)
{
logger.Info("JobToBeExecuted");
}
public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
{
// Raise the event on executed
OnJobExecuted(EventArgs.Empty);
logger.Info("JobWasExecuted");
}
public string Name
{
get
{
return "JobListener";
}
}
// Event raiser
protected virtual void OnJobExecuted(EventArgs args)
{
// This code will prevent IllegalThreadContext exceptions
EventHandler jobExecHandler = JobExecutedHandler;
if (jobExecHandler != null)
{
ISynchronizeInvoke target = jobExecHandler.Target as ISynchronizeInvoke;
if (target != null && target.InvokeRequired)
{
target.Invoke(jobExecHandler, new object[] { this, args });
}
else
{
jobExecHandler(this, args);
}
}
}
}
触发作业时,作业已执行(控制台打印"拍卖执行"),但作业侦听器的 JobWasExecute 不会选取它。谁能帮我解决这个问题?
其他问题:是否有另一种方法可以调用主窗体的方法?此外,作业侦听器类是否会在整个应用程序中持续存在(理论上不会关闭)。谢谢。
问题解决了。实现 IJobListener 类时,Name 属性受到保护,添加到 ListenerManager 时,它会覆盖上一个条目。技巧是在实例化 JobListener 类并将其添加到
:public string Name
{
get
{
return instanceName + "JobListener";
}
}
我今天遇到了类似的事情,我有(log4net)调试行,这些行在我的JobWasExecute方法中没有输出任何内容,即使JobToBeExecute中的类似行正在工作。 在敲打了大约两个小时后,我在作业成功完成后通过引发自定义异常来摆脱它。 ("黑客"部分是必须提出一个异常,以使JobWasExecute在我真的只是想获取最终工作状态时做出反应。
我想如果我为一个不平凡的项目这样做,我只会让我的工作将消息放到队列中(并观看),并且我可能会错过一些我应该在外出时在我的工作上设置的东西来引发事件,但我仍然发现 Quartz.NET 世界的这一部分非常混乱。
我的情况相似,但原因不同 - 以为我会在这里分享它,以防其他人有同样的问题。事件和听众似乎并没有被解雇。我正在动态创建作业/触发器,从数据库中提取触发器开始时间。问题是,尽管我从数据库中提取的日期时间是 UTC,但在 C# 中使用时,它并没有标记为 UTC(而是本地)。这些作业正在被安排,但在未来 9 小时内,我预计它们会在一分钟内触发。将日期时间标记为 UTC 解决了这个问题:
DateTime NextExecutionStartDate = DateTime.SpecifyKind(myDBObject.NextExecutionStartDate, DateTimeKind.Utc);
...Trigger.StartAt(NextExecutionStartDate)
而不是
...Trigger.StartAt(myDBObject.NextExecutionStartDate)