nopcommerce计划任务分析
对比了一下nopcommerce和orchard的计划任务,orchard的复杂的不是一点点,如果想拆下来自己用难度很大,搜索拆了orchard的lucene处理模块,邮件队列拆的discuznt和nopcommerce的结合,计划任务就拆nopcommerce的了,discuznt计划任务设计的没nopcommerce的好。
1.nopcommerce的tasks结构如下:
IScheduleTaskService.cs 接口,这个主要是获取数据库里的任务信息,ScheduleTaskService.cs去实现它就可以了,当然需要在容器里注入一下。
ITask 这个接口比较特别但是很重要,所有的任务处理类都要实现里面唯一的Execute方法。执行计划任务时就需要通过反射来执行这个实现。
namespace Nop.Services.Tasks { /// <summary> /// Interface that should be implemented by each task /// </summary> public partial interface ITask { /// <summary> /// Execute task /// </summary> void Execute(); } }
核心类之一:Task.cs,这个主要是处理任务的执行过程及执行过程类的结果处理。
private ITask CreateTask() { ITask task = null ; if ( this .Enabled) { var type2 = System.Type.GetType( this ._type); if (type2 != null ) { task = Activator.CreateInstance(type2) as ITask; } // this._enabled = task != null; } return task; }
通过反射来找到编写的计划任务类。例如下面的发送邮件的任务。
using System; using Nop.Core.Infrastructure; using Nop.Services.Logging; using Nop.Services.Tasks; namespace Nop.Services.Messages { /// <summary> /// Represents a task for sending queued message /// </summary> public partial class QueuedMessagesSendTask : ITask { /// <summary> /// Executes a task /// </summary> public void Execute() { var queuedEmailService = EngineContext.Current.Resolve<IQueuedEmailService> (); var emailSender = EngineContext.Current.Resolve<IEmailSender> (); var maxTries = 3 ; var queuedEmails = queuedEmailService.SearchEmails( null , null , null , null , true , maxTries, false , 0 , 10000 ); foreach ( var queuedEmail in queuedEmails) { var bcc = String.IsNullOrWhiteSpace(queuedEmail.Bcc) ? null : queuedEmail.Bcc.Split( new char [] { ' ; ' }, StringSplitOptions.RemoveEmptyEntries); var cc = String.IsNullOrWhiteSpace(queuedEmail.CC) ? null : queuedEmail.CC.Split( new char [] { ' ; ' }, StringSplitOptions.RemoveEmptyEntries); try { emailSender.SendEmail(queuedEmail.EmailAccount, queuedEmail.Subject, queuedEmail.Body, queuedEmail.From, queuedEmail.FromName, queuedEmail.To, queuedEmail.ToName, bcc, cc); queuedEmail.SentOnUtc = DateTime.UtcNow; } catch (Exception exc) { var logger = EngineContext.Current.Resolve<ILogger> (); logger.Error( string .Format( " Error sending e-mail. {0} " , exc.Message), exc); } finally { queuedEmail.SentTries = queuedEmail.SentTries + 1 ; queuedEmailService.UpdateQueuedEmail(queuedEmail); } } } } }
using System; using Nop.Core.Infrastructure; using Nop.Services.Logging; using Nop.Services.Tasks; namespace Nop.Services.Messages { /// <summary> /// Represents a task for sending queued message /// </summary> public partial class QueuedMessagesSendTask : ITask { /// <summary> /// Executes a task /// </summary> public void Execute() { var queuedEmailService = EngineContext.Current.Resolve<IQueuedEmailService> (); var emailSender = EngineContext.Current.Resolve<IEmailSender> (); var maxTries = 3 ; var queuedEmails = queuedEmailService.SearchEmails( null , null , null , null , true , maxTries, false , 0 , 10000 ); foreach ( var queuedEmail in queuedEmails) { var bcc = String.IsNullOrWhiteSpace(queuedEmail.Bcc) ? null : queuedEmail.Bcc.Split( new char [] { ' ; ' }, StringSplitOptions.RemoveEmptyEntries); var cc = String.IsNullOrWhiteSpace(queuedEmail.CC) ? null : queuedEmail.CC.Split( new char [] { ' ; ' }, StringSplitOptions.RemoveEmptyEntries); try { emailSender.SendEmail(queuedEmail.EmailAccount, queuedEmail.Subject, queuedEmail.Body, queuedEmail.From, queuedEmail.FromName, queuedEmail.To, queuedEmail.ToName, bcc, cc); queuedEmail.SentOnUtc = DateTime.UtcNow; } catch (Exception exc) { var logger = EngineContext.Current.Resolve<ILogger> (); logger.Error( string .Format( " Error sending e-mail. {0} " , exc.Message), exc); } finally { queuedEmail.SentTries = queuedEmail.SentTries + 1 ; queuedEmailService.UpdateQueuedEmail(queuedEmail); } } } } }
执行完任务后需要将数据库里的任务记录状态更改,主要是时间状态变更。
核心执行方法:
/// <summary> /// 执行任务 /// </summary> public void Execute() { this ._isRunning = true ; try { var task = this .CreateTask(); if (task != null ) { this ._lastStartUtc = DateTime.UtcNow; task.Execute(); this ._lastEndUtc = this ._lastSuccessUtc = DateTime.UtcNow; } } catch (Exception exc) { this ._enabled = ! this .StopOnError; this ._lastEndUtc = DateTime.UtcNow; // log error var logger = EngineContext.Current.Resolve<ILogger> (); logger.Error( string .Format( " Error while running the '{0}' schedule task. {1} " , this ._name, exc.Message), exc); } try { // find current schedule task var scheduleTaskService = EngineContext.Current.Resolve<IScheduleTaskService> (); var scheduleTask = scheduleTaskService.GetTaskByType( this ._type); if (scheduleTask != null ) { scheduleTask.LastStartUtc = this .LastStartUtc; scheduleTask.LastEndUtc = this .LastEndUtc; scheduleTask.LastSuccessUtc = this .LastSuccessUtc; scheduleTaskService.UpdateTask(scheduleTask); } } catch (Exception exc) { Debug.WriteLine( string .Format( " Error saving schedule task datetimes. Exception: {0} " , exc)); } this ._isRunning = false ; }
任务管理类:TaskManager.cs,主要负责任务的初始化,添加到线程列表,任务的开始和停止。需要在Global里初始化和开始任务,它会根据线程里的定时器自动读取任务列表执行任务。
// 开始执行任务 if (databaseInstalled) { TaskManager.Instance.Initialize(); TaskManager.Instance.Start(); }
任务线程管理类:TaskThread.cs,任务线程类,TaskManager将任务都添加到此线程管理类里,此线程管理主要负责判断任务的执行状态,线程执行间隔时间及调用任务执行的主方法Execute,通过Timer定时器实现定时自动运行。
主方法为:
private void Run() { if (_seconds <= 0 ) return ; this ._startedUtc = DateTime.UtcNow; this ._isRunning = true ; foreach (Task task in this ._tasks.Values) { task.Execute(); } this ._isRunning = false ; }
从任务列表中读取任务并执行。
以上是简单的分析,目前只是拿来主义,在学习和整理的同时加深一下对开源代码的理解。
独立博客地址: http://www.jqpress.com/post/190.aspx
标签: nopcommerce , 计划任务
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于nopcommerce计划任务分析的详细内容...