I am creating an application that uses Quartz.NET, which is utilised within a Windows service. There is also an administration backend written in ASP.NET, where administrators can add jobs and monitor the state of the scheduler. I am however having issues with the ASP.NET backend.
The connection is made in the Global.asax file, which seems to work at first - when the user logs on to the main dashboard, it works fine. The problem is when the user clicks onto a different page, where it then says the scheduler 'schedService' already exists.
Here is my Windows Service code:
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "schedService";
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = threadcount;
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["quartz.jobStore.misfireThreshold"] = "60000";
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
properties["quartz.jobStore.useProperties"] = "false";
properties["quartz.jobStore.dataSource"] = "default";
properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
//
properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
properties["quartz.scheduler.exporter.port"] = "555";
properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
properties["quartz.scheduler.exporter.channelType"] = "tcp";
//
// if running MS SQL Server we need thisl
properties["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz";
// config file
properties["quartz.dataSource.default.connectionString"] = connection;
properties["quartz.dataSource.default.provider"] = "SqlServer-20";
ISchedulerFactory schedService = new StdSchedulerFactory(properties);
IScheduler sched = schedService.GetScheduler();
ASP.NET Global.asax code:
public static IScheduler Sched()
{
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "schedMaintenanceService";
properties["quartz.scheduler.proxy"] = "true";
properties["quartz.scheduler.proxy.address"] = "tcp://localhost:555/QuartzScheduler";
ISchedulerFactory sf = new StdSchedulerFactory(properties);
IScheduler sched = sf.GetScheduler();
return sched;
}
Then I use this in each ASP.NET page:
public static IScheduler sched = Project.Global.Sched();
you should write your IScheduler as a singleton
I had a similar issue with the "scheduler already exists". I created a singleton class and I was able move past my issue.
The singleton code looks like this if anybody can use it. The lock is to avoid the issue from before when having more threads trying to get the same instance at once.
using Quartz;
using Quartz.Impl;
namespace MyProject.CommonObjects.Utilities
{
public static class QuartzFactory
{
private static object _locker = new object();
private static IScheduler _schedulerInstance;
public static IScheduler SchedulerInstance
{
get
{
lock (_locker)
{
if (_schedulerInstance == null)
_schedulerInstance = StdSchedulerFactory.GetDefaultScheduler();
return _schedulerInstance;
}
}
}
}
}
I found another solution. By giving each scheduler a different name I was able to work around the issue. I find this a better solution than the singleton one.
NameValueCollection properties = new NameValueCollection
{
[StdSchedulerFactory.PropertySchedulerInstanceName] = "MyNewScheduler1"
};
StdSchedulerFactory fac = new StdSchedulerFactory(properties);
_scheduler = fac.GetScheduler();
_scheduler.Start();
来源:https://stackoverflow.com/questions/4594742/quartz-net-remoting-scheduler-already-exists