“调度程序已存在问题”仍然存在

时间:2014-10-23 09:03:11

标签: c# quartz.net job-scheduling

即使我已将 Tarun Arora solution用于

  

名称为xxx的计划程序已存在。

问题,我仍然得到同样的错误。这是他的解决方案,我认为他已经正确实现了 Singleton 模式:

public class Scheduler
{
    public readonly IScheduler Instance;
    public string Address { get; private set; }
    public string JobName { get; set; }
    public string JobGroup { get; set; }
    public int Priority { get; set; }
    public string CronExpression { get; set; }

    private readonly ISchedulerFactory _schedulerFactory;


    public Scheduler(string server, int port, string scheduler)
    {
        Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler);
        _schedulerFactory = new StdSchedulerFactory(GetProperties(Address));

        try
        {
            Instance = _schedulerFactory.GetScheduler();

            if (!Instance.IsStarted)
                Instance.Start();
        }
        catch (SchedulerException ex)
        {
            throw new Exception(string.Format("Failed: {0}", ex.Message));
        }
    }

    private static NameValueCollection GetProperties(string address) 
    {
        var properties = new NameValueCollection();
        properties["quartz.scheduler.instanceName"] = "ServerScheduler";
        properties["quartz.scheduler.proxy"] = "true";
        properties["quartz.threadPool.threadCount"] = "0";
        properties["quartz.scheduler.proxy.address"] = address;
        return properties;
    }

    public IScheduler GetScheduler()
    {
        return Instance;
    }
}

我必须承认我没有使用他所说的最后一部分

  

如果您想调用Scheduler,那么您应该使用某些东西   比如下面的代码示例...

public SchedulerMetaData GetMetaData()
{
        var scheduler = new Scheduler("ServerName", Convert.ToInt32("PortNumber"), "Scheduler"));
        return scheduler.GetMetaData();
}

这是我在我的应用程序中调用调度程序的方法:

IScheduler sched = new Scheduler(logger, "127.0.0.1", 555, "QuartzScheduler").Instance;
IJobDetail postbagjob = null;
ITrigger postbagJobTrigger = null;
try
{
    postbagjob = JobBuilder.Create<PostbagJob>()
        .WithIdentity(jobName, jobGroup)
        .UsingJobData("CampaignId", campaignId.ToString())
        .UsingJobData("CampaignType", campaignType)
        .Build();
    postbagJobTrigger = (ICronTrigger)TriggerBuilder.Create()
        .WithIdentity(triggerName, triggerGroup)
        .WithCronSchedule(cron)
        .StartAt(DateTime.Now)
        .Build();
}
catch (SchedulerException ex)
{
    MsgBox.Show(ex.Message);
}

我第一次添加作业时有效,但第二次调用时,sched变为null

2 个答案:

答案 0 :(得分:1)

我已经测试了该实现,它似乎有效 您的解决方案中必须存在其他内容,以防止事情正常工作。

您确定服务器中正在运行的作业是PostbagJob吗?

我建议您检查服务器的配置。确保你有这样的东西:

                        

<add key="quartz.scheduler.exporter.type" value="Quartz.Simpl.RemotingSchedulerExporter, Quartz"/>
<add key="quartz.scheduler.exporter.port" value="555"/>
<add key="quartz.scheduler.exporter.bindName" value="QuartzScheduler"/>
<add key="quartz.scheduler.exporter.channelType" value="tcp"/>
<add key="quartz.scheduler.exporter.channelName" value="httpQuartz"/>

关于 cron 触发器,您能告诉我们什么?你能发布cron表达吗? 为什么不尝试将其更改为简单触发器并查看其工作原理:

postbagJobTrigger = (ISimpleTrigger)TriggerBuilder.Create()
        .WithIdentity("SampleTrigger", "QUARTZGROUP")
        .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).RepeatForever())
        .StartNow()
        .Build();

您应该做的另一件事是与服务器和客户端之间的作业共享一个程序集,以便它们具有相同的签名。

我对Scheduler课程进行了一些更改。您可以找到最终结果here

注意:

要运行服务器和客户端,请确保在解决方案中配置多个启动项目(右键单击解决方案)。

<强>更新

更好的方法是以这种方式创建单例类:

public sealed class QuartzScheduler
{
    private static QuartzScheduler instance = null;

    private static readonly object padlock = new object();

    private readonly ISchedulerFactory SchedulerFactory = null;
    private readonly IScheduler Scheduler = null;

    QuartzScheduler()
    {
        this.SchedulerFactory = new StdSchedulerFactory();
        this.Scheduler = this.SchedulerFactory.GetScheduler();
    }

    public static IScheduler Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new QuartzScheduler();
                }
                return instance.Scheduler;
            }
        }
    }
}

如果你想read更多,你可以在Jon Skeet的博客上找到很多有用的信息。
注意:我使用过第三个版本。

现在您只需在Windows窗体应用程序中使用该对象:

QuartzScheduler.Instance.ScheduleJob(postbagjob, postbagJobTrigger);

仅此而已。

如果您查看我的 github repo,您可以找到有效的解决方案。
我在app.config文件中移动了客户端配置;我想这更容易定制:

<quartz>
    <add key="quartz.threadPool.type" value="Quartz.Simpl.ZeroSizeThreadPool, Quartz" />
    <add key="quartz.scheduler.instanceName" value="RemoteClient"/>
    <add key="quartz.threadPool.threadCount" value="0"/>
    <add key="quartz.scheduler.proxy" value="true"/>
    <add key="quartz.scheduler.proxy.address" value="tcp://127.0.0.1:555/QuartzScheduler"/>
</quartz>

要记住的另一件事是您的客户端正在调度作业,而不是真正运行调度程序,因此您应该将线程池配置为ZeroSizeThreadPool

答案 1 :(得分:0)

对于Quartz Web服务,重新启动应用程序池可解决此问题。