Compared with the planned tasks of nopcommerce and orchard, orchard is not a little complicated. If you want to split it, it is very difficult to use it. Search and split orchard's Lucene processing module, the combination of discuznt and nopcommerce in the mail queue, the planned task is to remove nopcommerce, and the design of the discuznt scheduler task is not good.
1. The tasks structure of nopcommerce is as follows:
Ischeduletaskservice. CS interface, which is mainly used to obtain the task information in the database. It can be implemented by scheduletaskservice. cs. Of course, you need to inject it into the container.
The itask interface is special but important. All Task Processing classes must implement the unique execute method. Execute a scheduled task through reflection.
Namespace Nop. Services. Tasks { /// <Summary> /// Interface that shoshould be implemented by each task /// </Summary> Public Partial Interface Itask { /// <Summary> /// Execute task /// </Summary> Void Execute ();}}
One of the core classes is task. CS, which is mainly used to process the execution process of the task and the result processing of the execution process class.
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 ;}
You can use reflection to find the scheduled task class. For example, the following mail sending task.
View code
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 QueuedemailIn 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 );}}}}}
After the task is executed, you need to change the status of the task records in the database, mainly the time status change.
Core execution method:
/// <Summary> /// Execute task /// </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 ;}
Task Management class: TASKMANAGER. CS, mainly responsible for task initialization, addition to the thread list, task start and stop. Tasks must be initialized and started in global. tasks are automatically read from the task list based on the timer in the thread.
//Start task executionIf(Databaseinstalled) {TASKMANAGER. instance. initialize (); TASKMANAGER. instance. Start ();}
Task thread management class: taskthread. CS, task Thread class, and taskmanager add tasks to this thread management class. This thread management is mainly responsible for judging the execution status of tasks, the thread execution interval and the main method of calling the task execution execute. The timer is used to implement timed automatic operation.
The main method is:
Private Void Run (){ If (_ Seconds <= 0 ) Return ; This . _ Startedutc = Datetime. utcnow; This . _ Isrunning = True ; Foreach (Task In This . _ Tasks. Values) {task. Execute ();} This . _ Isrunning = False ;}
Read and execute a task from the task list.
The above is a simple analysis. At present, it is just a matter of learning and organizing.Source code.
Independent blog address: http://www.jqpress.com/post/190.aspx