如何在Orchard中运行定时任务?

4
我需要每隔5小时运行一次自动化任务。我在这篇文章中发现了如何创建定时任务,使用IScheduledTaskHandler和IScheduledTaskManager。 Scheduled tasks using Orchard CMS 我复制了相同的代码,在Process函数中添加了我的服务调用。它编译得很好。但是我不确定我是否必须像启动Windows服务那样“启动”此计划任务。如果我想要在5小时内运行此作业,它会自动被捕获吗?如果我想要停止/暂停,我该怎么做?
谢谢。
编辑:
如果我尝试启用具有任务处理程序的自定义模块,则会出现异常。
异常详细信息:System.ArgumentNullException:值不能为 null。 参数名:source
Line 241: var shellContext = _shellContexts.FirstOrDefault(c => c.Settings.Name == settings.Name);

源文件:\orchard-1.4\src\Orchard\Environment\DefaultOrchardHost.cs 行:241

_shellContexts 为空。如果我从项目/模块中删除任务处理程序类,则一切正常。

这是任务处理程序代码。

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


}

这是由FirstOrDefault()抛出的通用异常 - _shellContexts由于某种原因为null。你能展示一下你的任务处理器代码吗?顺便说一下 - 检查一下任务处理器应该如何编写,例如在Orchard.PublishLater模块中。也许你做错了什么。但在看到整个情况之前无法确定任何事情。 - Piotr Szmyd
代码与其他示例中的几乎相同。我已将其粘贴在上面。 - user471317
查看错误日志,我看到了这个异常............................... Autofac.Core.DependencyResolutionException: 在类型 'MyServices' 的构造函数 'Void .ctor(Orchard.IOrchardServices, Orchard.Data.ISessionFactoryHolder, Orchard.Data.ISessionLocator, IMyQuery)' 调用时引发了异常 ---> System.NullReferenceException: 对象引用未设置到对象的实例。 在 MyServices..ctor(IOrchardServices orchardServices, ISessionFactoryHolder sessionFactoryHolder, ISessionLocator sessionLocator, IMyQuery myQuery) - user471317
你是否试图在 MyServices 构造函数中执行某些可能会引发空引用异常的操作?不要在那里放置任何复杂逻辑,或者确保你进行必要的检查。 - Piotr Szmyd
这是失败的那一行.............................................................................................................. contentrepo = _orchardServices.WorkContext.Resolve<IRepository<SomeRecord>>(); - user471317
显示剩余2条评论
3个回答

5
当你启动应用程序时,时钟会自动开始计时 - 你无法停止/暂停它。
调度程序以1分钟的间隔运行 - 它会检查是否有应该运行的任务,并运行它们。任务被存储在数据库中 - 相应的记录总是在任务执行即将开始之前删除(以确保给定的任务仅运行一次)。
如果您需要运行一个重复的作业,您需要在上一个作业完成后立即创建一个新的任务(就像您链接的示例中那样)。

“当你启动应用程序”是什么意思?这个任务处理程序在我的一个自定义模块中。我猜想当这个模块从管理员控制面板启用时,时钟开始计时? - user471317
就是这样 - 当应用程序启动时。任务调度程序是Orchard中的一个默认组件 - 它始终在后台运行。你所说的任务处理程序是一个类,由调度程序每分钟调用一次。实际上可以有(并且事实上有)很多任务处理程序(来自其他模块) - 调度程序会抓取它们全部并每分钟调用每个处理程序一次。 - Piotr Szmyd

1

如果有人感兴趣,我已经从ScheduledTaskHandler中简单地删除了启动代码。接下来,我将其放在一些控制器构造函数中。

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

并在处理程序上

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

0
使用 ILoggerFactory 替代 ILogger,然后从中获取 Logger 实例。
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);
        }
    }

抱歉,我没有仔细阅读并认为这是记录器问题。有一个问题,你的服务接口(IMyService)是否实现了IDependency? - ZafarYousafi
是的,它确实实现了IDependency。 - user471317

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接