zoukankan      html  css  js  c++  java
  • 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

     
     
  • 相关阅读:
    [bzoj1911][Apio2010特别行动队] (动态规划+斜率优化)
    [bzoj1597][usaco2008 mar]土地购买 (动态规划+斜率优化)
    [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
    整体二分初步
    bzoj[3238][ahoi差异]
    概率dp学习
    poj[2104]K-th Number
    hdu[1711]number sequence
    hdu[2222]keywords search
    poj[1187][Noi 01]陨石的秘密
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2554959.html
Copyright © 2011-2022 走看看