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://HdhCmsTestjqpress测试数据/post/190.aspx
标签: nopcommerce , 计划任务
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于nopcommerce计划任务分析的详细内容...