How to schedule tasks using Quartz.Net inside a Windows Service? - c#

I have created a windows service project in VS and in it I configure Quartz.Net to run a task immediately. The code that registers the task runs with no exception, but the task is never executed as far as my debugging can tell.
I can't be sure because debugging a Windows Service is very different. The way I do it is to programatically launching the debugger from my code. Quartz.Net runs jobs on a separate threads, but I'm not sure if VS2010 can see other running threads when debugging a Windows Service.
Has anyone done what I'm trying before? Any tips are appreciated.
PS. I don't want to use Quartz.Net's own Service.

One of the most common reasons a job doesn't execute, is because you need to call the Start() method on the scheduler instance.
http://quartznet.sourceforge.net/faq.html#whytriggerisntfiring
But it's hard to say what the problem is if we don't have some sort of snippet of the code that does the scheduler creation and job registration.

I see that this is a bit dated, but it came up many times in various searches!
Definitely check out this article, which uses an XML config when the scheduler is instantiated.
http://miscellaneousrecipesfordotnet.blogspot.com/2012/09/quick-sample-to-schedule-tasks-using.html
In case you would rather not use XML (dynamically created tasks and such), replace the "Run" procedure from the article above with something like this:
public void Run()
{
// construct a scheduler factory
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
_scheduler = schedulerFactory.GetScheduler();
IJobDetail job = JobBuilder.Create<TaskOne>()
.WithIdentity("TaskOne", "TaskOneGroup")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("TaskOne", "TaskOneGroup")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(20).RepeatForever())
.Build();
_scheduler.ScheduleJob(job, trigger);
_scheduler.TriggerJob(job.Key);
_scheduler.Start();
}
Note - Using Quartz .NET 2.1.2, .NET 4
Cheers!

I have successfully used Quart.NET before in a Windows service. When the service starts-up I create the Scheduler Factory and then get the Scheduler. I then start the scheduler which implicitly reads in the configuration XML I have specified in the App.config of the service.
Quartz.NET basic setup: http://quartznet.sourceforge.net/tutorial/lesson_1.html
App.config Setup Question: http://groups.google.com/group/quartznet/browse_thread/thread/abbfbc1b65e20d63/b1c55cf5dabd3acd?lnk=gst&q=%3Cquartz%3E#b1c55cf5dabd3acd

Related

Running Quartz.net on another server

I have a Windows Forms application where users can define certain tasks to be scheduled, but I want to run them on another server. I was thinking that I could schedule the tasks using Quartz.NET with the AdoJob scheduler, so they will be in a database, and on the same server as the database I would have a Windows Service which could read the scheduled jobs and execute them. How should I do this in Quartz.NET? Or is this not the best approach for my problem?
Update: Here's what I'm trying.
Schedule a task from the app using the type name of the class which should be executed
I tried with Quartz.NET to schedule a job using the name and namespace of the class, but it doesn't work, instead of using a direct reference to it. If this would have worked, the next step would've been to start the windows service and see if I could run the job from there.
IJobDetail job = JobBuilder.Create(Type.GetType("SomeNamespace.IHelloJob"))
.WithIdentity("myJobRemote", "remote")
.StoreDurably()
.Build();
The exception message says "Job class cannot be null."
If I make the first step work, then I'll start the windows service and try to run the job inside of it

Automatic run function for ever c# Quartz.net

I use Quartz.net in website for run job forever, and i want run job Automatically in server in every 15 min.
My problem is, User must visit site until application start in global.asax run and it works when user is in site, I want run job without visiting site and start it for ever without users be in site
I am using this code for running job in global.asax
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
SchedulerDemo.Interfaces.ISchedule myTask = new SchedulerDemo.Jobs.HelloSchedule();
myTask.Run();
}
By default in Quartz.net, the jobs list and their trigger will be stored in memory, so as you have suspected, it will have to be defined in the Application_Start to be called on the first request.
You first need to get and start the scheduler in itself.
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
Then, still in your Application_Start method, you will have to define the job and it's trigger :
// Instantiating the job
IJobDetail jobDetail = JobBuilder.Create<MyJob>()
.WithIdentity(new JobKey("MyVeryImportantJob", "VeryImportantJobGroup"))
.Build();
ITrigger jobTrigger = TriggerBuilder.Create()
.WithIdentity(new TriggerKey("MyVeryImportantJobTrigger", "VeryImportantJobTriggerGroup"))
.WithCronSchedule("* 0/15 * * * ?"") // execute every 15 min (in reality at HH:00, HH:15, HH:30 and HH:45)
.Build();
And join the two to schedule the job
scheduler.ScheduleJob(jobDetail, jobTrigger);
The scheduler will then manage to call your job according to the trigger you defined (in this case, every 15 min).
Also, as Quartz.Net will spawn a dedicated thread for the scheduler, it won't impact iis response process and it will prevent the iis worker to be recycled, so once it's launched, it will run forever until either the iis website or the host server is restarted.
After that, if you REALLY want your scheduler to start with the website without any request at all, you can use the Service Auto Start Provider (more info here :
https://www.simple-talk.com/blogs/2013/03/05/speeding-up-your-application-with-the-iis-auto-start-feature/
)

Birthdays Reminder Code for Asp.Net MVC

I want to create a web application in MVC Asp.Net for Hotel Room Booking and Customers Management. I am having trouble with one of the requirement. I want to create a code for Sending SMS to Customers on their Birthdays for Wishing them from Hotel. I am confused, that where should i place the code for checking customers with birthdate same as today's Date, so that Code gets Triggered every day at 12:00 am even if the web application is not launched. Please can you explain where should i insert the code?
There is a open-source library called Quarz which will help you with that.
There is a very good blog article by Mike Brind about this library. The library provides a fluent API which allows you to do exactly what you want.
The following code (based on the example of the mentioned blog article) creates a event which is called every day at 12 o´clock:
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<BirthdayJob>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithDailyTimeIntervalSchedule
(s =>
s.WithIntervalInHours(24)
.OnEveryDay()
.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(12, 0))
)
.Build();
scheduler.ScheduleJob(job, trigger);
It can run in the context of the Website, a Windows Service or even a WinForms-Application (as long the user doesn't closes it).
Depending on the context you need to schedule the job in different places. For a Website in would be the Application_Start()-Method. For a Service this would be the OnStart()-Method.
Additionally you need a class "BirthdayJob" which will provide the actual code which should be executed periodically:
public class BirthdayJob : IJob
{
public void Execute(IJobExecutionContext context)
{
// Check for birthdays...
}
}
There is one point you should be aware of if you call this code in the context of a website:
It's possible that the IIS puts your website to sleep if it isn't requested for a while. In this case it would be possible that the scheduled tasks are not executed.
There is an option to change the timeout for your website:
In the IIS manager go to "Application Pools", find the application pool that is used for your website and select "Properties" -> "Performance". There you can set the idle timeout. There are several other approaches to solve this problem.
However, if your website is requested frequently you would never see this problem.
The best way to go would be to call Quarz from a Windows-Service which runs even if your websites sleeps or lays down drunken under a table.
You could ship a service together with your web application which does the periodic checks and runs separately from the site.
Another usage of this service could be general maintenance of the data store which is used by the site, thus, for instance, once a day it would archive information, check birthdays and any other maintenance or periodic tasks, such as the issuing of reminders, etc. which your platform would issue.

Schedule a C# console application

I've given a task to create an email C# console application which targeted to run as batch. I'm very new to C# area and hence I have no idea about my direction. This C# console application will be deployed on a server and expect to run in certain time based on server time.
After some research, most of the suggestions are about using task scheduler or window services, but I'm wondering if this C# console application is somehow possible to run own its own? Maybe after execute it, it then register itself into the server and the server will handle it periodically?
If you want to manage the scheduler by code have a look at Quartz.NET: http://quartznet.sourceforge.net/
This library provides the creation of jobs and triggers.
e.g. (directly from: http://quartznet.sourceforge.net/tutorial/lesson_3.html):
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(DumbJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTime = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
Now this means your console application should run continuously which makes it not really suitable for the job.
Option 1. Add a task via task scheduler (real easy) that executes your console application. See example task: http://www.sevenforums.com/tutorials/12444-task-scheduler-create-new-task.html
Option 2. Create a windows service (not to complicated) that uses a library like Quartz.NET or .NET's Timer class to scheduele jobs and executes a batch operation. See for creation of windows service http://msdn.microsoft.com/en-us/library/zt39148a.aspx
Option 3. Make your console application implement a scheduele library like Quartz.NET or /Net's Timer class and run it as a service (a bit more complex): Create Windows service from executable
As long as it requires no user input, it will be able to run on it's own. You can schedule the program to run in Windows Task Scheduler for example.

Scheduler doesn't execute job, doesn't appear to even register it

I've created the following:
A windows service
A quartz scheduler class
A single IJob implementation called Worker, which contains a set of tasks that I intend to execute via the Quartz scheduler.
The windows service overrides OnStart to call the scheduling/setup class, which attempts to create a single scheduled task within Quartz that I want to run at a given time frame (At the moment, this is simply once per 30 seconds for example, to test the process)
I've used identical code to one of the samples for creating a job and trigger - the trigger containing a chain of code to start immediately and repeat every 30 seconds, forever.
I then call Schedule() and eventually call Start() on the scheduler object.
I use installutil.exe to shove the Service into the services list, I start the service and see my internal logging framework showing me that the service is starting, the scheduler is being created and the job scheduled (logging output line by line since I've been having issues...) The problem is that the task doesn't run once and doesn't ever repeat. The service sits there running happily, but never spins up to execute anything.
If I use the Exists method, passing in the JobKey - it always says false. The count of Jobs is zero, both tested immediately after scheduling and starting the scheduler.
I am setting up the IJobDetail using this approach:
IJobDetail job = JobBuilder.Create<Worker>()
.WithIdentity("job1", "group1")
.Build();
and creating the Trigger with:
TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.ForJob(job)
.StartAt(DateTime.Now)
.WithSimpleSchedule(x => x.WithIntervalInSeconds(30).WithRepeatCount(10))
.Build();
and then to hook it up:
sched.ScheduleJob(job, trigger);
sched.Start();
I am at a loss as to why this is happening, there is nothing in the event log and nothing wrong with the service and the code appears to run through without any problems as I've shoved logging statements (output to txtfile within /bin/debug) after every line & there's plenty of exception handling.
Any ideas? Is the Build() on the generic Create going to tell the scheduler that the type I've defined is where the Execute() method resides?
Edit
Configuration sections I nabbed from this post on SO (#jadenedge's answer) and placed within app.config for the Windows Service. Possibility here of 1.0/2.0 mismatch?
I want the configuration within app.config, ideally, and have no other configuration elsewhere.
Are you starting a thread that keeps the process running? After the service is started, is your process still in memory?
I had this problem and oh boy it drove me absolutely crazy. As it happened I had a spike project that I could always get to run, but my main projects would not run!
The problem: The namespace of my project had dots/periods in it e.g.MyProject.UpdateService where as my spike was simply named QuartzTest.
Debugging through line by line found that when I set my Windows service name to MyProjectUpdateService the Quartz job then registered.
TL/DR:
Ensure your Windows service doesn't have dots in the name.
Update: I've done some more testing and it looks like the maximum length of the service name for a Windows service running Quartz is 25 characters. It doesn't error - it just won't start.

Categories

Resources