【问题标题】:Quartz.net same job executed twice at same time in asp.netQuartz.net 相同的作业在 asp.net 中同时执行两次
【发布时间】:2018-07-06 11:26:32
【问题描述】:

我正在使用 Quartz 库 2.3.3.0 版在每天早上 8 点和下午 4 点所需的时间执行电子邮件发送作业。该网站现已上线,过去两天一直在正确的时间发送电子邮件。然而,今天早上 8 点发生了该工作被执行了两次,并且所有的电子邮件也被发送了两次。为此,我设置了一个日志表来监控在正确时间执行的电子邮件作业的状态。在今天的日志中,每条记录都被插入了两次。我不知道为什么会这样。下面是我为此功能运行的代码。

JobScheduler.cs

public class JobScheduler
    {
        public static void Start()
        {
            IJobDetail emailJob = JobBuilder.Create<EmailJob>()
                  .WithIdentity("job1")
                  .Build();

            ITrigger trigger = TriggerBuilder.Create().WithDailyTimeIntervalSchedule
                  (s =>
                     s.WithIntervalInSeconds(30)
                    .OnEveryDay()
                  )
                 .ForJob(emailJob)
                 .WithIdentity("trigger1")
                 .StartNow()
                 .WithCronSchedule("0 0/1 * * * ?") // Time : Every 1 Minutes job execute
                 .Build();

            ISchedulerFactory sf = new StdSchedulerFactory();
            IScheduler sc =  sf.GetScheduler();
             sc.ScheduleJob(emailJob, trigger);
             sc.Start();
        }
    }

EmailJob.cs

public void Execute(IJobExecutionContext context)
        {
            //check for date and time of event
            //if starttime and date is tomorrow then send reminder email
            //if starttime and date is today then send reminder email

            string time = DateTime.Now.ToString("h:mm tt");

            if (time == "4:00 PM" || time == "8:00 AM")
            {
                InsertLogMessage("Entring Email Job Execute Function if "+ time);

                GetAllBookings();
            }

        }

        private List<int> GetAllBookingsTimes()
        {
            InsertLogMessage("Getting all booking times when time is " + DateTime.Now.ToShortTimeString());

            List<int> lst = new List<int>();
            try
            {

                //Select for upcoming event of today and tomorrow
                conn = Database.getInstance();
                conn.Open();

                cmd = new SqlCommand("ReminderEmails", conn);
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Action", "CheckForReminder");

                reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    Times t = new Times();

                    t.iTimesId = Convert.ToInt32(reader["TimesId"]);

                    if (!lst.Contains(t.iTimesId))
                    {
                        lst.Add(t.iTimesId);
                    }
                }

                conn.Close();

            }
            catch (Exception ex)
            {
                InsertLogMessage(ex.Message);
            }

            InsertLogMessage("Returning to Bookings after scheduled times");

            return lst;
        }

        private void GetAllBookings()
        {
            InsertLogMessage("Getting Booking w.r.t times");

            Dictionary<int, List<Booking>> dicofbooking = new Dictionary<int, List<Booking>>();

            try {

                List<int> timesid = GetAllBookingsTimes();

                foreach(var item in timesid)
                {
                    //Get email status confirmation 
                    bool status = GetEmailStatus(item.ToString());

                    if (status == false)
                    {
                        List<Booking> bookinglst = new List<Booking>();
                        bookinglst = CheckForReminder().Where(p => p.tTimes.iTimesId == item).ToList();
                        dicofbooking.Add(item, bookinglst);
                    }
                }

                blist = new List<Booking>();
                bcclst = new List<string>();

                foreach (var item in dicofbooking)
                {
                    foreach (var item1 in item.Value)
                    {
                        if (item1.tTimes.dtDateTime.Date == DateTime.Now.Date || item1.tTimes.dtDateTime.Date == DateTime.Now.Date.AddDays(1))
                        {
                            //Send email at particular time
                            if (bcclst.Contains(item1.mMember.strEmailAddress) == false)
                            {
                                bcclst.Add(item1.mMember.strEmailAddress);
                                blist.Add(item1);
                            }
                        }
                    }

                    if (blist.Count > 0)
                    {
                        InsertLogMessage("Sending Email for "+ blist[0].eEvent.strEventTitle + " " + blist[0].tTimes.iTimesId);
                        if (SendEmail(blist[0]))
                        {
                            InsertLogMessage("Email sent successfully for " + blist[0].eEvent.strEventTitle + " " + blist[0].tTimes.iTimesId);
                            //Set Reminder Email Status to true
                            UpdateEmailStatus(blist[0].tTimes.iTimesId.ToString());
                        }
                    }

                    blist = new List<Booking>();
                    bcclst = new List<string>();

                }

            }
            catch (Exception ex)
            {
                InsertLogMessage(ex.Message);
            }


        }

【问题讨论】:

  • 如果您想在特定时间发送电子邮件,我建议您使用 Windows 服务或计划任务。如果您的网站被回收、离线或处于睡眠模式(通常在 20 分钟不活动后),则不会发送邮件。
  • 它总是发送。在这种情况下,它发送了两次。
  • Start() 在何时何地被调用?
  • Email Job 类中的 Execute 方法调用 Start。并且每隔 1 分钟。这就是为什么我认为它永远不会在后台睡觉的原因。

标签: asp.net quartz.net


【解决方案1】:

此问题是由于在 30 秒和 60 秒等条件下执行触发器所致。

s.WithIntervalInSeconds(30)

WithCronSchedule("0 0/1 * * * ?")

还提到了作业“执行”功能,并与它的日期时间进行比较,可能会在 30 秒内同时被触发。 更改触发器如下

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/15 8,16 * * ?"))
    .forJob("myJob", "group1")
    .build(); 

将作业“执行”功能更改为

public void Execute(IJobExecutionContext context)
        {
                InsertLogMessage("Entring Email Job Execute Function if "+ time);
                GetAllBookings();
        }

此触发器将每 15 分钟触发一次,但仅在上午 8 点和下午 4 点执行。 无需再次检查日期时间。

【讨论】:

    【解决方案2】:

    我猜您要加载配置两次,一次是使用 ContextLoaderListener,一次是在 DispatcherServlet 中导致重复。检查你的配置。

    【讨论】:

    • web.config 文件中没有使用这样的关键字。你在说什么。
    • 你没有使用spring框架吗?我已经根据spring框架给出了评论。显示网络配置文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 2017-07-31
    相关资源
    最近更新 更多