How does one implement the background scheduled tasks of a WEB site?

Source: Internet
Author: User

1. Why should the WEB site use background scheduled tasks?
Someone may ask, why do I need to customize the background scheduled tasks for the WEB site itself?
In fact, it is very simple. Anyone who has done practical WEB applications knows it. Some background operations such as statistics, evaluation, and data update are often performed on an actual site. Some of the tasks are repeated regularly, of course, the administrator can regularly execute the Click event on the developed web page (as you know, IIS executes the background program only when the client responds ).
In addition, some Click operations have a long IIS response time. For example, the author used an application last year to evaluate the XX problem in a region, because a model system is executed in the background, it takes about 3 minutes to get the result after clicking (haha, can you afford this ?). At this time, you can use the background scheduled task to implement it in advance, and store or break down the results into fast response tasks.

2. How to Implement
The first thing I think of is the timer. Before I develop myself, I first checked the achievements of my predecessors on the internet according to my previous habits. I did not expect anyone to think about it and I did it too. Here we will not analyze it any more. The following is an excerpt from the original article:

ASP.net background Processing Technology

In ASP.net WEB development, we often encounter the following problem: Slow user operation response.

This situation may occur because user operations are time-consuming operations. . Net program is designed in the background when the user submits the operation. After the processing is complete, the operation result is returned to the user. In a smaller system, this design is simple and easy, and the performance does not have much problems. However, in a larger system, this design will give users a poor operation experience, this affects users' impression of the system.

In the system I previously implemented, there are generally two ways to deal with this situation: 1. record user operations directly to the backend database for regular scanning by the background program. Ii. Use Asp.net's timed processing method to process the data directly on the WEB server layer.

There is no big difference between the two methods. The first method mainly requires a background program to complete the scanning.

Here I will briefly introduce the second method.

Its core processing is System. Threading. Timer. This scheduled class can be used to periodically execute user submission operations in the background,

Its Usage:

System. Threading. TimerCallback t = new System. Threading. TimerCallback (your solution );

System. Threading. Timer t = new System. Threading. Timer (t, null, 1000,5000 );

This section indicates that the specified proxy is called every five seconds after 1 second of startup.

In specific implementation, I define three classes.

1. BkExecItem is used to save the user's submitted operations. It can also be serialized to the disk to avoid the loss of key background tasks.

2. BkExec is used for execution. It calls the method specified in BkExecItem through reflection. In addition, it also maintains

The first-out Queue <BkExecItem> records all background processing items.

3. BkManager initializes the timer and configures the module parameters.

Well, we will summarize it here for the time being. Next time, I will post the code for your reference.

Trackback: http://tb.blog.csdn.net/TrackBack.aspx? PostId = 1681816

A Practical ASP. Net background processing class. This time I will discuss with you about ASP.net background processing and refer to the codes of a background processing class applied in our current project.

Background processing is also a problem that needs to be considered in the current management system design.

What is background processing? You can simply think that this process is not completed in user process processing, but is put into the server background process for processing.

After being added to the background processing, the operation speed of foreground users can be improved and the user operation experience can be improved.

Generally, a user's basic requirement for a system is to respond in a timely manner. It is difficult for the user to have a liking for a management system that needs to wait 10 seconds after the operation is submitted, however, in actual system running, user operations are difficult to get response in a short time, So background processing can play a role at this time.

In the subsequent post code, I define all tasks to be processed in the background as an ExecItem object. after the user submits the operation, the system will convert the operation into an ExecItem object and add it to a first-in-first-out queue in BkExecManager (background processing management object.

When the website is started, BkExecManager is automatically started, while BkExecManager starts a timer to regularly process backend task queues.

BkExecManager removes the task object in the queue when the processing is completed. If the operation fails, the Administrator will be notified by email to complete the troubleshooting.

Oh. paste the code now!

1. Manage objects in the background
Public class BkExecManager
{// Timed callback.
Private static TimerCallback timerDelegate;
Private static Timer stateTimer;
Private static BkExecer m_Execer;
Public static string DataPath;
Public static string BkManager = "XXXX ";
Public static int BkBufSize = 100;

Private static int Interval = 10000;

Public static BkExecer Execer
{
Get {return m_Execer ;}
}

Static BkExecManager ()
{
DataPath = System. AppDomain. CurrentDomain. BaseDirectory + "BkItem \\";

If (System. Configuration. ConfigurationManager. receivettings ["Interval"]! = Null)
Interval = Convert. ToInt32 (System. Configuration. ConfigurationManager. deleettings ["Interval"]);
If (System. Configuration. ConfigurationManager. receivettings ["BkBufSize"]! = Null)
BkBufSize = Convert. ToInt32 (System. Configuration. ConfigurationManager. deleettings ["BkBufSize"]);
If (system. configuration. configurationmanager. deleetmanager ["bkmanager"]! = NULL)
Bkmanager = system. configuration. configurationmanager. deleetmanager ["bkmanager"];

M_execer = new bkexecer ();

// Initialization callback
Timerdelegate = new timercallback (m_execer.dobkexec );

// Initialize the timer
Statetimer = new timer (timerdelegate, null, 5000, interval );

}

/// <Summary>
/// Stop the timer.
/// </Summary>
Static void bkexecquit ()
{
Statetimer. Dispose ();
}
}

2. background processing and execution
Public class bkexecer
{
// Maintenance 1
Forward and forward queues.
Private queue <execitem> m_bkexecitemlist;
Private Static object lockhelper = new object ();
Private Static bool m_isbusy = false;
Public static bool isbusy
{
Get
{
Return m_isbusy;
}
}

Public bkexecer ()
{
M_BkExecItemList = new Queue <ExecItem> (BkExecManager. BkBufSize );

//// Read the pending items
InitData ();
}

Private void InitData ()
{
Lock (lockHelper)
{
String [] fnl = Directory. GetFiles (BkExecManager. DataPath );
Foreach (string s in fnl)
{
If (! S. Contains (BKExecItemState. Error. ToString ()))
{
ExecItem ei = ExecItem. GetObject (s );
M_BkExecItemList.Enqueue (ei );
}

}
}
}

Public void AddBkExecItem (ExecItem ei)
{
Lock (lockHelper)
{
// Lock the resource.
M_BkExecItemList.Enqueue (ei );
}
}

Public void DoBkExec (object Msg)
{
ExecItem ei;

While (m_BkExecItemList.Count> 0)
{
Lock (lockHelper)
{
Ei = m_bkexecitemlist.dequeue ();
}

Int Rv =-1;

Try
{
Bindingflags flags = bindingflags. invokemethod | bindingflags. instance |
Bindingflags. Public | bindingflags. Static;

Object T = ei. execitemclass. invokemember (Ei. execitemmethed, flags, null, null, ei. execitemparamlist );
If (T! = NULL)
Rv = convert. toint32 (t );
Else
Rv = 0; // if no return is returned, set zero directly.
}
Catch (Exception e)
{
// Update the Ei status and save it to the disk.
Ei. FinishBkExec (false, e. Message );
}
Finally
{
// Update the Ei status and delete the storage.
// Save it to the disk.
If (rv> = 0)
Ei. FinishBkExec (true ,"");
Else
EI. finishbkexec (false, RV. tostring ());
}
}
}
}

3. task object

Public Enum bkexecitemstate {waiting for execution, complete, error };

[Serializable]
/// <Summary>
/// Background command set
/// Directly serialize these background commands to the Web server for storage.
/// If it is complete, it will be deleted from the web server.
/// Send an email to the administrator if an exception occurs.
/// </Summary>
Public class ExecItem
{
/// <Summary>
/// Disk document name.
/// </Summary>
Private string BKStoreFileName = "";

Private string ErrMsg = "";

Private BKExecItemState m_ItemState;

Public BKExecItemState ItemState
{
Get {return m_ItemState ;}
}

Private datetime m_execitemexectime;

Public datetime execitemexectime
{
Get {return m_execitemexectime ;}

}

Private datetime m_execitemcreatetime;

Public datetime execitemcreatetime
{
Get {return m_execitemcreatetime ;}

}
Private string m_execitemname;

Public String execitemname
{
Get {return m_execitemname ;}

}
Private type m_execitemclass;

Public type execitemclass
{
Get {return m_execitemclass ;}

}
Private string m_execitemmethed;

Public String execitemmethed
{
Get {return m_ExecItemMethed ;}

}
Private object [] m_ExecItemParamList;

Public object [] ExecItemParamList
{
Get {return m_ExecItemParamList ;}

}

Private string m_Op;

/// <Summary>
/// Background task object
/// </Summary>
/// <Param name = "objtype"> Object Type </param>
/// <Param name = "ExecMethod"> call method </param>
/// <Param name = "param"> call parameters </param>
/// <Param name = "ExecName"> Task name </param>
/// <Param name = "Op"> submitted by </param>
/// <Param name = "SavetoDisk"> whether to save to disk </param>
Public ExecItem (Type objtype, string ExecMethod, object [] param, string ExecName, string Op, bool SavetoDisk)
{
This. BKStoreFileName = String. format ("{0} {1} {2 }. bin ", DateTime. now. toString ("yyyy-MM-dd HH-mm-ss"), ExecMethod, Op );
This. m_ExecItemClass = objtype;
This. m_ExecItemCreateTime = DateTime. Now;
This. m_ExecItemExecTime = DateTime. Now;
This. m_ExecItemMethed = ExecMethod;
This. m_ExecItemName = ExecName;
This. m_ExecItemParamList = param;
This. m_ItemState = BKExecItemState. To be executed;
This. m_Op = Op;

If (SavetoDisk)
SaveToDisk ();
}

Private void SaveToDisk ()
{
IFormatter formatter = new BinaryFormatter ();
Stream stream = new FileStream (BkExecManager. DataPath + BKStoreFileName, FileMode. Create, FileAccess. Write, FileShare. None );
Formatter. Serialize (stream, this );
Stream. Close ();
}

Private void SaveToDisk2 ()
{
//
String basedir = System. AppDomain. CurrentDomain. BaseDirectory;
This. BKStoreFileName = String. format ("{0} {1} {2} {3 }. bin ", m_ExecItemCreateTime.ToString (" yyyy-MM-dd HH-mm-ss "), this. m_ExecItemMethed, m_Op, m_ItemState.ToString ());

Iformatter formatter = new binaryformatter ();

Stream stream = new filestream (bkexecmanager. datapath + bkstorefilename, filemode. Create, fileaccess. Write, fileshare. None );
Formatter. serialize (stream, this );
Stream. Close ();
}

Public static execitem GetObject (string S)
{
Iformatter formatter = new binaryformatter ();

Stream stream = new FileStream (s, FileMode. Open, FileAccess. Read, FileShare. None );
ExecItem e = (ExecItem) formatter. Deserialize (stream );
Stream. Close ();
Return e;
}

Public void FinishBkExec (bool DoneOk, string Msg)
{
String FileName = BkExecManager. DataPath + BKStoreFileName;
M_ExecItemExecTime = DateTime. Now;

If (File. Exists (FileName ))
File. Delete (FileName );

If (! DoneOk)
{
M_ItemState = BKExecItemState. error;
ErrMsg = Msg;
SaveToDisk2 ();
MakeMail ();
}
}

Private void MakeMail ()
{
StringBuilder sb = new StringBuilder ();
Sb. Append ("submitted by:"). Append (this. m_Op). Append ("<BR> ");
Sb. Append ("submission time:"). Append (this. ExecItemCreateTime). Append ("<BR> ");
Sb. Append ("Object:"). Append (this. m_ExecItemClass.Name). Append ("<BR> ");
Sb. Append ("method:"). Append (this. m_ExecItemMethed). Append ("<BR> ");
Sb. Append ("parameter :");
Foreach (object o in this. m_ExecItemParamList)
Sb. Append (o. ToString (). Append (",");
Sb. Append ("<BR> ");
Sb. Append ("execution time:"). Append (this. m_ExecItemExecTime). Append ("<BR> ");
Sb. Append ("error message:"). Append (this. ErrMsg). Append ("<BR> ");
String mb = sb. ToString ();

// APP. Mail. Send (m_Op + ":" + m_ExecItemClass.Name + "background processing error", mb, "", BkExecManager. BkManager ,"");
}
}

The specific call method is
1. First, call a new background task object.
2. Add it to the task queue.

ExecItem ei = new ExecItem (typeof (CacheManager), "RefreshObject", new object [] {Objtype, Params, ct}, "cache refresh", "", false ); // you can set it to false in the future, that is, the refresh task is not saved to the disk to avoid affecting disk performance.
BkExecManager. Execer. AddBkExecItem (ei );

Now this object works well in our project.

In the future, I want to continue to improve this object. Its shortcomings include: the user is not informed of the progress and result of the Operation submitted by the user.

Trackback: http://tb.blog.csdn.net/TrackBack.aspx? PostId = 1768124

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.