Quartz.NET - 乔布斯不运行?

时间:2010-11-24 17:08:41

标签: c# quartz-scheduler quartz.net

我正在尝试在C#中将Quartz.NET实现为Windows服务。当我期望它们触发时,我的工作并没有触发......实际上,就我所知,实际上是什么?

我的“我的工作”计划在“精确”运行后的下一个连续分钟开始运行。然而,当下一分钟到来时,我似乎无法判断是否有任何实际运行。

我认为当我的工作运行时,会在执行作业时弹出一个CLI窗口,并且可以看到控制台操作,(我甚至在其中放置Console.ReadKey()以确保窗口没有打开,收盘这么快,我看不到它,但据我所知,时间表根本就没有执行工作。

我注意到所有时间都是UTC,并且StartTimeUtc将被设置为UTC时间,这是我本地计算机时间+6小时,但我还假设Quartz调度程序处理通过我的TimeZone设置计算执行时间,虽然我无法确认,或确认我的日程安排的实际时间。

我想有一些方法可以设置Common Logging程序集并利用它来帮助我了解我的状态,但是我还没弄清楚该怎么做以启用任何类型的日志以获取来自Windows的反馈服务,除了写入我为它创建的事件日志。

我的Windows服务的OnStart功能

protected override void OnStart(string[] args)
    {
        eventLog.WriteEntry("--- STARTING eLoyalty Scheduler Service ---");

        // construct a scheduler factory
        ISchedulerFactory schedFact = new StdSchedulerFactory();

        // get a scheduler
        IScheduler sched = schedFact.GetScheduler();

        // construct job info
        JobDetail jobDetail = new JobDetail("eLoyaltySchedulerService", null, typeof(PortalSchedulerJob));
        jobDetail.JobDataMap["jobSays"] = "eLoyalty Scheduler Service Executing!";
        jobDetail.JobDataMap["myStateData"] = new ArrayList(); 

        // fire every minute
        Trigger trigger = TriggerUtils.MakeMinutelyTrigger();

        // start on the next even minute
        trigger.StartTimeUtc = TriggerUtils.GetEvenMinuteDate(DateTime.UtcNow);

        // name it
        trigger.Name = "NextEvenMinute";

        // schedule it
        sched.ScheduleJob(jobDetail, trigger);

        // start the schedule
        sched.Start();

        eventLog.WriteEntry("--- STARTED eLoyalty Scheduler Service ---");
    }

My Job的Execute()函数如下:

public void Execute(JobExecutionContext context)
    {
        try
        {
            string instName = context.JobDetail.Name;
            string instGroup = context.JobDetail.Group;
            JobDataMap dataMap = context.MergedJobDataMap;
            string jobSays = dataMap.GetString("jobSays");
            ArrayList state = (ArrayList)dataMap["myStateData"];
            state.Add(DateTime.UtcNow);

            Console.WriteLine("Instance {0} of PortalSchedulerJob says: {1} @ {2}", instName, jobSays, DateTime.UtcNow);
            Console.ReadKey();
        }
        catch (JobExecutionException Ex)
        {
            throw Ex;
        }
    }

如果您可以帮我弄清楚如何解决我的ACTUAL日程安排活动,我可以自己解决这个问题吗?

5 个答案:

答案 0 :(得分:9)

在Quartz.NET任务中,您只能引发JobExecutionException异常: Quartz.net- Lesson 3

  

Job.Execute(..)方法最后,我们   需要告诉你一些细节   IJob.Execute(..)方法。唯一的   允许的异常类型   从execute方法中抛出是   JobExecutionException。因为   这个,你通常应该包装   execute方法的全部内容   带有'try-catch'块。你应该   也花了一些时间看着   的文档   JobExecutionException,就像你的工作一样   用它来提供调度程序   关于你想要的各种指令   要处理的例外。

而不是:

catch (JobExecutionException Ex)
{
   throw Ex;
}

做这样的事情:

catch (Exception err)
{
    // Only allow JobExecutionException exceptions to be thrown...
    throw new Quartz.JobExecutionException(err);
}

然后,您可以集中处理异常:

_globalJobListener = new GlobalJobListener();
sched.AddGlobalJobListener(_globalJobListener);


public class GlobalJobListener : Quartz.IJobListener
{
    public GlobalJobListener()
    {
    }

    public virtual string Name
    {
        get { return "MainJobListener"; }
    }

    public virtual void JobToBeExecuted(JobExecutionContext context)
    {       
    }

    public virtual void JobWasExecuted(JobExecutionContext inContext, JobExecutionException inException)
    {
        if (inException != null)
        {
            // Log/handle error here
        }
    }


    public virtual void JobExecutionVetoed(JobExecutionContext inContext)
    {

    }
}

答案 1 :(得分:2)

您可以在调试时始终在控制台中运行Windows服务:

static class Program
{
    static void Main()
    {
        var servicesToRun = new ServiceBase[] 
            { 
                new CassetteDeckService() 
            };

        if (Environment.UserInteractive)
        {
            var type = typeof(ServiceBase);
            const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
            var method = type.GetMethod("OnStart", flags);

            foreach (var service in servicesToRun)
            {
                method.Invoke(service, new object[] { null });
            }

            Console.WriteLine("Service Started!");
            Console.ReadLine();

            method = type.GetMethod("OnStop", flags);

            foreach (var service in servicesToRun)
            {
                method.Invoke(service, null);
            }
            Environment.Exit(0);
        }
        else
        {
            ServiceBase.Run(servicesToRun);
        }
    }
}

只需确保在Windows服务项目的属性中将应用程序类型更改为控制台应用程序(当它不以交互模式运行时,这不会影响它作为Windows服务运行)。

答案 2 :(得分:0)

我们遇到了触发器失火的一些问题。我added a global trigger listener捕获与解雇工作相关的事件,并提供调试问题所需的信息。

我们还通过Common.Logging连接NLog以捕获Quartz的内部日志记录(您可能会注意到我们自己使用Simple Logging Facade,因此这里也配置了组件)。这是我们的应用程序配置,希望可以启动你:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <section name="slf" type="Slf.Config.SlfConfigurationSection, slf"/>
        <sectionGroup name="common">
            <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
        </sectionGroup>
    </configSections>


    <quartz>
        <add key="quartz.threadPool.threadCount" value="20" />
        <add key="quartz.jobStore.misfireThreshold" value="420000" /><!-- 7 minutes -->
    </quartz>


    <slf>
        <factories>
            <factory name="nlog" type="SLF.NLogFacade.NLogLoggerFactory, SLF.NLogFacade"/>
        </factories>

        <loggers>
            <logger factory="nlog"/>
        </loggers>
    </slf>

    <common>
        <logging>
            <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog">
                <arg key="configType" value="FILE" />
                <arg key="configFile" value="~/NLog.config" />
            </factoryAdapter>
        </logging>
    </common>

</configuration>

答案 3 :(得分:0)

感谢大家的投入......遗憾的是,我无法使用任何此类功能,但是当我将一个事件记录器添加到我的Job执行功能时,我发现它每分钟都会写入事件日志如预期的那样。

我想Console.WriteLine()Console.ReadKey() funcs在Windows服务环境中什么都不做?

注意:他们做了一些事情,但在后台作为服务运行而不是在控制台窗口中运行......

答案 4 :(得分:0)

如果你想调试你的工作,请在你的工作代码中打开visual studio:

System.Diagnostics.Debugger.Launch();

这将允许您附加到visual studio中的调试器,您可以看到正在发生的事情。

或者,如果你想让常见的日志记录工作,请给我发一条消息,因为我在Windows服务中一切正常。