Automatic run function for ever c# Quartz.net - c#

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/
)

Related

Are Azure Web Jobs capable of keeping the task running in background?

I am currently experiencing difficulties with running a long HTTP request in a Web Job. Same application runs fine when started on local machine. Since I've tried multiple ways of trying to make this work I am now curious if this is possible at all.
My testing code below:
static void Main(string[] args)
{
/// [...]Getting configuration and using it in "SendPayload"
_stopwatch = new Stopwatch();
_stopwatch.Start();
Task.Run(async () => { await SendPayloadAndAwait(configuration); });
while (_isWaiting)
{
if (_stopwatch.ElapsedMilliseconds % 5000 == 0)
{
Console.WriteLine(".");
}
}
}
public static async Task<string> SendPayloadAndAwait (RequestModel targetRequest)
{
/// [...]Preparing client and payload
Console.WriteLine("Start");
Response= curClient.SendAsync(req).Result;
var endContent = Response.Content.ReadAsStringAsync().Result;
Console.WriteLine("End");
_isWaiting = false;
return "Done";
}
The "End" is never printed in Web Job console, it is an infinite (up to the point of timeout) loop of ".". Is such scenario somehow prohibited?
The way I solved at a previous company was by having the long running job in a Web API which was implemented as an Azure Function was
First call (i.e. /api/StartJob)
creates a job entry (in azure table)
starts backgound thread
returns a 202 [Accepted] status with the job entries Id
Background thread performs long running task updating job entry with it's progress
Client Loop (while percentage done < 100)
Requests status (i.e. /api/JobStatus)
If percentage done = 100 exit loop
This was very successful and reliable providing we had a paid for plan
The free plans kill the session after approx 5 minutes (by design)
You will need to enable the "Always on" setting to make sure your long-running job doesn't get terminated.
The web app times out after 20 minutes of inactivity, and only the requests to the actual web app resets this timer. The web jobs are executed asynchronously in a separate process, so they don't keep the web app "awake".
Here's a note from the web jobs documentation:
A web app can time out after 20 minutes of inactivity. and only requests to the actual web app can reset the timer. Viewing the app's configuration in the Azure portal or making requests to the advanced tools site (https://<app_name>.scm.azurewebsites.net) doesn't reset the timer. If you set your web app to run continuous or scheduled (timer-trigger) WebJobs, enable the Always on setting on your web app's Azure Configuration page to ensure that the WebJobs run reliably. This feature is available only in the Basic, Standard, and Premium pricing tiers.

ASP .NET - Quartz Scheduler only Executes jobs on user visit

I need my emails to be sent automatically from my .NET application. However, when scheduling jobs for the future, the jobs are only executing when a user visits the site.
Global.asax.cs
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
JobScheduler.Start();
}
Job Scheduler (ScheduledTasks.cs)
public class EmailJob : IJob
{
public void Execute(IJobExecutionContext context)
{
BDL.Utilities.sendEmailNotification(to, subject, body);
}
}
public static void start()
{
foreach (AspNetUser user in users)
{
IJobDetail job = JobBuilder.Create<EmailJob>().WithIdentity((jobidentity))
.UsingJobData("to", user.Email)
.UsingJobData("subject", subject)
.UsingJobData("body", bodyholder).Build();
ITrigger trigger = TriggerBuilder.Create()
// schedule for 1 day in the future
.StartAt(expdate.AddDays(1)))
.WithIdentity(triggerid)
.Build();
scheduler.ScheduleJob(job, trigger);
}
}
I have scheduled a trigger for 1 day in the future. This trigger should cause my job to execute 1 day in the future. However, for some reason this job will only execute if a user visits my site on the day the job is scheduled to fire. How can I make these Jobs be executed automatically by Quartz???
EDIT: My goal is to accomplish this without messing with the Application Pool threads. The accepted answer shows that this question is about merely replacing the user interaction with automated scripts. Whereas the duplicate asks for a way to maintain the application pool threads, and in Java I might add!
+1 to #BRAHIMKamel. You could consider using Hangfire to do some job processing in your ASP.NET application.
Be aware though, that as long as you rely on IIS application pool, your job could be terminated and restarted at any time. That means that your job code must tolerate multiple subsequent executions. Regarding e-mails that means that you should check whether you've already sent what you want before attempting to actually send message.
I was able to come up with a more elegant solution. Using the tool Zapix I was able to schedule my website to be quality checked every 20 minutes. Zapix simply visited the site and received and http response. By using Zapix, it mimicked the functionality of manually visiting the website to trigger the emails.

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.

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

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

Categories

Resources