好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

nopcommerce计划任务分析

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计划任务分析的详细内容...

  阅读:44次

上一篇: 网络爬虫基本原理(二)

下一篇:Lua开篇