1

几天来,我一直在努力完成这项工作。我正在尝试使用石英调度程序在我的主窗体上触发一个事件,从中可以调用一个方法。我的主窗体上的代码如下:

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

当作业被触发时,作业被执行(控制台打印“auction exec”)但作业侦听器的 JobWasExecuted 没有拾取它。谁能帮我解决这个问题?

附加问题:还有其他方法可以调用主窗体的方法吗?此外,作业侦听器类是否会在整个应用程序中持续存在(理论上不会关闭)。谢谢。

4

3 回答 3

4

问题解决了。在实现 IJobListener 类时,Name 属性受到保护,当添加到 ListenerManager 时,它会覆盖之前的条目。诀窍是在实例化 JobListener 类并将其添加到:

public string Name
{
    get
    {
        return instanceName + "JobListener";
    }
}
于 2013-01-28T08:53:36.103 回答
0

我今天遇到了类似的事情,我有(log4net)调试行在我的 JobWasExecuted 方法中没有输出任何内容,即使 JobToBeExecuted 中的类似行正在工作。在击败它大约两个小时后,我通过在我的工作成功完成后引发自定义异常来破解它。(当我真的只是想获取最终的工作状态时,“hack”部分必须引发异常以让 JobWasExecuted 做出反应。)

我想如果我是为一个不平凡的项目做这件事,我只会让我的工作将消息放到一个队列中(并观察它),并且我可能会错过一些我应该在我的工作中设置的东西提出一个事件,但我仍然发现 Quartz.NET 世界的这一部分非常混乱。

于 2014-09-09T17:57:40.617 回答
0

我的情况类似,但有不同的原因 - 我想我会在这里分享它,以防其他人有同样的问题。事件和听众似乎没有被解雇。我正在动态创建作业/触发器,从数据库中提取触发器开始时间。问题是虽然我从数据库中提取的日期时间是 UTC,但在 C# 中使用时并没有标记为 UTC(而是本地)。这些工作正在安排中,但在未来 9 小时内,我预计它们会在一分钟内触发。将日期时间标记为 UTC 解决了这个问题:

DateTime NextExecutionStartDate = DateTime.SpecifyKind(myDBObject.NextExecutionStartDate, DateTimeKind.Utc);

...Trigger.StartAt(NextExecutionStartDate)

代替

...Trigger.StartAt(myDBObject.NextExecutionStartDate)
于 2014-12-09T19:45:28.027 回答