问题
I have to run a automated job every 5 hours.
I found this post on how to create scheduled tasks, using IScheduledTaskHandler and IScheduledTaskManager. Scheduled tasks using Orchard CMS
I copied the same code, I added my service call inside the Process function. It compiles fine. But I am not sure if I have to 'start' this scheduled task, like a windows service start. Does it get picked up automatically after I build the solution? When does the clock starts ticking if I want to run this job in 5 hours? And if I want to stop/pause, how can I do that?
Thanks.
EDIT:
I am getting an exception if I try to enable the custom module with task handler.
Exception Details: System.ArgumentNullException: Value cannot be null. Parameter name: source
Line 241: var shellContext = _shellContexts.FirstOrDefault(c => c.Settings.Name == settings.Name);
Source File: \orchard-1.4\src\Orchard\Environment\DefaultOrchardHost.cs Line: 241
The _shellContexts is coming up as null. If I remove the task handler class from the project/module, everything works fine.
Here is the task handler code.
public class ScheduledTaskHandler : IScheduledTaskHandler
{
private const string TaskType = "MyTaskUniqueID";
private readonly IScheduledTaskManager _taskManager;
private readonly IMyService _myService;
public ILogger Logger { get; set; }
public ScheduledTaskHandler(IScheduledTaskManager taskManager, IMyService myService)
{
_myService = myService;
_taskManager = taskManager;
Logger = NullLogger.Instance;
try
{
DateTime firstDate = new DateTime().AddMinutes(5);
ScheduleNextTask(firstDate);
}
catch (Exception e)
{
this.Logger.Error(e, e.Message);
}
}
public void Process(ScheduledTaskContext context)
{
if (context.Task.TaskType == TaskType)
{
try
{
_myService.RunJob();
}
catch (Exception e)
{
this.Logger.Error(e, e.Message);
}
finally
{
DateTime nextTaskDate = new DateTime().AddHours(5);
ScheduleNextTask(nextTaskDate);
}
}
}
private void ScheduleNextTask(DateTime date)
{
if (date > DateTime.UtcNow)
{
var tasks = this._taskManager.GetTasks(TaskType);
if (tasks == null || tasks.Count() == 0)
this._taskManager.CreateTask(TaskType, date, null);
}
}
}
回答1:
Clock starts ticking automatically when you start the app - you cannot stop/pause it.
Scheduler runs in 1 minute intervals - it checks if there are tasks that should be ran now and runs them. Tasks are being stored in database - corresponding record is always deleted just before task execution is about to start (to ensure that a given task will run only once).
If you need a recurrent job to be ran, you need to create a new task just after the previous one has finished (like in the example you linked to).
回答2:
if somebody is interested I've simply removed the starter code from ScheduledTaskHandler. The following I put on some controller constructor
private void ScheduleStartTask() {
var tasks = _scheduledTaskManager.GetTasks(TaskType);
if (tasks == null || tasks.Count() == 0) {
var date = _clock.UtcNow.AddSeconds(5);
_scheduledTaskManager.CreateTask(TaskType, date, null);
}
}
and on the handler
public void Process(ScheduledTaskContext context) {
if (context.Task.TaskType == TaskType) {
try {
var x = "kuku";
} catch (Exception e) {
this.Logger.Error(e, e.Message);
} finally {
this.ScheduleNextTask();
}
}
}
private void ScheduleNextTask() {
var date = _clock.UtcNow.AddSeconds(5);
_taskManager.DeleteTasks(null, a => a.TaskType == TaskType);
_taskManager.CreateTask(TaskType, date, null);
}
回答3:
Use ILoggerFactory Instead of ILogger and then Get Logger Instance from it.
public ScheduledTaskHandler(IScheduledTaskManager taskManager,ILoggerFactory LoggerFactory, IMyService myService)
{
_myService = myService;
_taskManager = taskManager;
Logger = NLoggerFactory.CreateLogger(typeof(ScheduledTaskHandler));;
try
{
DateTime firstDate = new DateTime().AddMinutes(5);
ScheduleNextTask(firstDate);
}
catch (Exception e)
{
this.Logger.Error(e, e.Message);
}
}
来源:https://stackoverflow.com/questions/11475187/how-to-run-scheduled-tasks-in-orchard