1

私は数日間、これを機能させるのに苦労しています。Quartz スケジューラを使用して、メソッドを呼び出すことができるメイン フォームでイベントを発生させようとしています。メインフォームのコードは次のとおりです。

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

ジョブがトリガーされると、ジョブは実行されました (コンソールは「オークション実行」を出力します) が、ジョブ リスナーの JobWasExecuted はそれを取得しません。誰でもこれで私を助けることができますか?

追加の質問: メイン フォームのメソッドを呼び出す別の方法はありますか? また、ジョブ リスナ クラスは、アプリケーション全体 (理論上は閉じられません) を通じて持続します。ありがとう。

4

3 に答える 3

4

問題が解決しました。IJobListener クラスを実装すると、Name プロパティが保護され、ListenerManager に追加すると、以前のエントリが上書きされます。JobListener クラスをインスタンス化し、それを次のように追加するときに、カスタム文字列を追加するのがコツです。

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

今日、JobToBeExecuted の同様の行が機能していたにもかかわらず、JobWasExecuted メソッドで何も出力していない (log4net) デバッグ行があった、似たようなことに遭遇しました。約 2 時間試した後、ジョブが正常に完了した後にカスタム Exception を発生させることで、ハッキングから抜け出すことができました。(「ハック」部分は、本当に最終的なジョブ ステータスを取得したいときに、JobWasExecuted を反応させるために例外を発生させる必要があることです。)

自明ではないプロジェクトでこれを行っていたとしたら、ジョブにメッセージをキューにドロップさせて (そしてそれを監視して)、途中でジョブに設定する必要があるものを見逃している可能性があると思います。イベントを発生させましたが、Quartz.NET の世界のこの部分はかなり厄介でした。

于 2014-09-09T17:57:40.617 に答える
0

私の状況は似ていましたが、別の原因がありました。他の誰かが同じ問題を抱えている場合に備えて、ここで共有したいと思います. イベントとリスナーが起動していないようです。データベースからトリガーの開始時間を取得して、ジョブ/トリガーを動的に作成していました。問題は、データベースから取得した日時は UTC でしたが、C# で使用すると UTC としてマークされなかった (むしろローカル) ことです。ジョブはスケジュールされていましたが、1 分以内に起動すると予想していた将来の 9 時間でした。日時をUTCとしてマークすると、これが修正されました:

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

...Trigger.StartAt(NextExecutionStartDate)

それ以外の

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