【问题标题】:Quartz.NET trigger does not fire, MVC4Quartz.NET 触发器不触发,MVC4
【发布时间】:2013-12-09 21:18:08
【问题描述】:

我有一个基于 Unity 依赖注入的 3 层架构的 MVC4 .Net Web 应用程序,我想每天进行一次验证并发送一些邮件。为此我想在 Application_start 中使用 Quartz Scheduler,因为依赖注入 windows 服务不是一个好的选择。

这是我在 application_start 中的代码。

        // construct a scheduler factory
        ISchedulerFactory schedFact = new StdSchedulerFactory();
        IScheduler sched = schedFact.GetScheduler();
        sched.Start();

        IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(SchedulerJob));
        // fire every time I open App/EveryDay
        ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 1,
                                                 new TimeSpan(1, 0, 0, 0));
        sched.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger);

这是我的工作代码:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using EvaluationMvc.Bll.Contracts;
 using Quartz;
 using Quartz.Impl;

namespace EvaluationMvc.Utils
{
   public class SchedulerJob : IJob
   { 
      private IEvaluationBus _iEvaluationBus;

      public SchedulerJob(IEvaluationBus iEvaluationBus)
      {
        //Dependency injection
          _iEvaluationBus = iEvaluationBus; 

      }
      public void Execute(IJobExecutionContext context)
      {
        _iEvaluationBus.testingArchitecture();
       // Sends a test mail.
      }
  }
}    

但是我的工作从未执行,可能是什么问题?

【问题讨论】:

    标签: asp.net-mvc-4 quartz.net


    【解决方案1】:

    Quartz.net 调度程序必须创建为singleton

    您可以安装Unity.MVC4 NuGet 包。
    它将创建一个 Bootstrapper 类,该类应如下所示:

    public static class Bootstrapper
    {
        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
            return container;
        }
    
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
            // Register your interfaces here. 
            RegisterTypes(container);
            return container;
        }
    
        public static void RegisterTypes(IUnityContainer container)
        {
        }
    }
    

    然后您必须创建自己的 JobFactory 实现。这个article 可能会对你有所帮助,this one 值得一读:

    public class UnityJobFactory: IJobFactory
    {
        private readonly IUnityContainer container;
    
        static UnityJobFactory()
        {
        }
    
        public UnityJobFactory(IUnityContainer container)
        {
            this.container = container;
        }
    
        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            var jobDetail = bundle.JobDetail;
            var jobType = jobDetail.JobType;
    
            try
            {
                return this.container.Resolve(jobType) as IJob;
            }
            catch (Exception ex)
            {
                throw new SchedulerException(string.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot instantiate class '{0}'", new object[] { jobDetail.JobType.FullName }), ex);
            }
        }
    
        public void ReturnJob(IJob job)
        {
            // Nothing here. Unity does not maintain a handle to container created instances.
        }
    }
    

    以及您自己的 StdSchedulerFactory 实现:

    public class UnitySchedulerFactory : StdSchedulerFactory
    {
        private readonly UnityJobFactory unityJobFactory;
    
        public UnitySchedulerFactory(UnityJobFactory unityJobFactory)
        {
            this.unityJobFactory = unityJobFactory;
        }
    
        protected override IScheduler Instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs)
        {
            qs.JobFactory = this.unityJobFactory;
            return base.Instantiate(rsrcs, qs);
        }
    }
    

    回到你的 Unity Bootstrapper,你必须注册你的接口:

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
    
            container.RegisterType<ISchedulerFactory, UnitySchedulerFactory>(new ContainerControlledLifetimeManager());
            container.RegisterType<IScheduler>(new InjectionFactory(c => c.Resolve<ISchedulerFactory>().GetScheduler()));
            container.RegisterType<IQuartzScheduler, QuartzScheduler>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEvaluationBus, EvaluationBus>();
    
            RegisterTypes(container);
    
            return container;
        }
    

    我已将我的服务调度程序封装在一个类中,以便我可以将其创建为单例:

    public interface IQuartzScheduler
    {
        void Run();
        void Stop();
    }
    

    和:

    public class QuartzScheduler : IQuartzScheduler
    {
        private readonly ISchedulerFactory SchedulerFactory;
        private readonly IScheduler Scheduler;
    
        public QuartzScheduler(ISchedulerFactory schedulerFactory, IScheduler scheduler)
        {
            this.SchedulerFactory = schedulerFactory;
            this.Scheduler = scheduler;
        }
    
        public void Run()
        {
            IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(Scheduler.SchedulerJob));
            // fire every time I open App/EveryDay
            ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 10,
                                                     new TimeSpan(0, 0, 0, 20));
    
            this.Scheduler.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger);
    
            this.Scheduler.Start();
        }
    
        public void Stop()
        {
            this.Scheduler.Shutdown(false);
        }
    }
    

    正如您在本课程中所见,我将创建我的作业/触发器并启动调度程序。

    现在在您的 Application_Start (global.asax) 中,您可以“引导”您的 Unity 容器,获取服务调度程序并运行它。

    var unityContainer = Infrastructure.Bootstrapper.Initialise();
    unityContainer.Resolve<IQuartzScheduler>().Run();
    

    您可以在link (QuartzWithUnity) 之后找到一个工作示例。

    【讨论】:

    • 这对我帮助很大。谢谢!
    【解决方案2】:

    非常有用,感谢 LeftyX。我认为,在 Application_Start 中,您必须像这样创建服务:

    var unityContainer = Bootstrapper.Initialise();
    QuartzScheduler jobService = (QuartzScheduler)unityContainer.Resolve(typeof(QuartzScheduler), "Jobs");
    jobService.Run();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多