";调度程序已存在问题“;持续存在

本文关键字:存在 问题 quot 调度程序 | 更新日期: 2023-09-27 18:27:42

即使我使用了Tarun Arora的解决方案

名为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

";调度程序已存在问题“;持续存在

我已经测试了该实现,它似乎可以工作
你的解决方案中一定有其他东西阻碍了事情的正常运行。

您确定在服务器中运行的作业是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类做了一些更改。你可以在这里找到最终结果。

注意:

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

更新:

一个更好的方法是这样创建一个单例类:

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

如果你想阅读更多,你可以在Jon Skeet的博客上找到很多有用的信息
NB:我用了第三个版本

现在,您可以在windows窗体应用程序中简单地使用该对象:

QuartzScheduler.Instance.ScheduleJob(postbagjob, postbagJobTrigger);

仅此而已。

如果您查看我的github回购,您可以找到一个有效的解决方案
我已经在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

对于Quartz web服务,重新启动应用程序池解决了这个问题。