首页  ·  知识 ·  云计算
ASP.net实现WEB站点的后台定时任务
朝露绿客联盟  http://www.cnblogs.com/ding0910/  综合  编辑:dezai  图片来源:网络
采用Asp.net的定时处理方式,在WEB服务器层处理业务核心处理就是System.Threading.Timer。这个定时类可以用于在后台定时执行用户提交操作,

采用Asp.net的定时处理方式,在WEB服务器层处理业务
核心处理就是System.Threading.Timer。这个定时类可以用于在后台定时执行用户提交操作,


它的使用方法:

System.Threading.TimerCallback t=new System.Threading.TimerCallback (你的处理方法);
System.Threading.Timer t = new System.Threading.Timer(t,null,1000,5000);
 这一段说明是在启动1秒后每隔5秒就调用所指定的代理。

在具体实现时我定义了三个类。

1、BkExecItem用于保存用户提交操作,同时它也可以序列化到磁盘上,以免关键后台任务丢失。

2、BkExec用于执行。它通过反射来调用BkExecItem中所指定的方法。另外它中间还维护一个先入

先出队列Queue,这个队列记录全部的后台处理项。

3、BkManager完成定时器的初始化,模块的参数配置等功能。

呵,暂时总结到这里。下次我会将代码也贴上来,供大家参考下。

一个实用ASP.Net 后台处理类

呵.这回跟大家讨论下ASP.net 后台处理 ,并会把我们当前项目中应用的一个后台处理类的代码贴上来参考.

后台处理也是现在管理系统设计中需要考虑到的一个问题.

什么是后台处理,可以简单认为不是在用户进程处理中完成用户提交的操作,而是将这一处理放到服务端后台进程来处理.

加入后台处理后,可以提高前台用户的操作速度,改善用户操作体验.

对于一般用户来说他对于一个系统的基本要求就是响应及时,用户很难对一个提交操作后需要等待10秒以后的管理系统产生好感,但在实际系统运行中用户操作是很难在短时间内得到响应,所以这个时候后台处理就可以发挥作用了.

我在后面所帖代码中,将需要后台处理的任务均定义成一个ExecItem对象.用户提交操作后,系统将就操作转成一个ExecItem对象加入到BkExecManager(后台处理管理对象)中的一个先入先出的队列中.

网站在启动时会自动启动BkExecManager,而BkExecManager则启动一个定时器来定时处理后台任务队列.

在处理完成时BkExecManager就队列中移去任务对象,如果操作失败将以邮件方式通知管理员来完成问题处理.

呵.现在贴代码!

1,后台处理管理对象

 

public class BkExecManager

    //定时回调。
    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.AppSettings["Interval"] != null)
            Interval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Interval"]);

        if (System.Configuration.ConfigurationManager.AppSettings["BkBufSize"] != null)
            BkBufSize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["BkBufSize"]);

        if (System.Configuration.ConfigurationManager.AppSettings["BkManager"] != null)
            BkManager = System.Configuration.ConfigurationManager.AppSettings["BkManager"];

        m_Execer = new BkExecer();
        //初始化回调
        timerDelegate = new TimerCallback(m_Execer.DoBkExec);
        //初始化定时器
        stateTimer = new Timer(timerDelegate, null, 5000, Interval);
    }

    /**//**//**////


    /// 停止定时器.
    ///

    static void BkExecQuit()
    {
        stateTimer.Dispose();
    }
}
2,后台处理执行

 

public class BkExecer
{
    //维护一个前进前出的队列。
    private Queue 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(BkExecManager.BkBufSize);
        /**//**//**/////读入待处理事项
        InitData();
    }

    private void InitData()
    {
        lock (lockHelper)
        {
            string[] fnl = Directory.GetFiles(BkExecManager.DataPath);
            foreach (string s in fnl)
            {
                if (!s.Contains(BKExecItemState.出错.ToString()))
                {
                    ExecItem ei = ExecItem.GetObject(s);
                    m_BkExecItemList.Enqueue(ei);
                }
            }
        }
    }

    public void AddBkExecItem(ExecItem ei)
    {
        lock (lockHelper)
        {
            //锁定资源。
            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;     //如果是无返回则直接设置零.
            }
            catch (Exception e)
            {
                //更新Ei的状态,保存到磁盘。
                ei.FinishBkExec(false, e.Message);
            }
            finally
            {
                //更新Ei的状态,删除存件
                //保存到磁盘。
                if (rv >= 0)
                    ei.FinishBkExec(true, "");
                else
                    ei.FinishBkExec(false, rv.ToString());
            }
        }
    }
}
3,任务对象


public enum BKExecItemState { 待执行, 完成, 出错 };

[Serializable]
/**//**//**////


/// 后台命令集合
/// 直接将这些后台命令二进制序列化到WEb服务器上保存。
/// 如果完成后则从Web服务器上删除。
/// 如果异常则发邮件通知管理员。
///

public class ExecItem
{
    /**//**//**////
    /// 磁盘文档名称 。
    ///

    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;
    /**//**//**////


    /// 后台任务对象
    ///

    /// 对象类型
    /// 调用方法
    /// 调用参数
    /// 任务名
    /// 提交人
    /// 是否保存到磁盘
    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.待执行;
        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.出错;
            ErrMsg = Msg;
            SaveToDisk2();
            MakeMail();
        }
    }

    private void MakeMail()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("提交人:").Append(this.m_Op).Append("
");
        sb.Append("提交时间:").Append(this.ExecItemCreateTime).Append("
");
        sb.Append("对象:").Append(this.m_ExecItemClass.Name).Append("
");
        sb.Append("方法:").Append(this.m_ExecItemMethed).Append("
");
        sb.Append("参数:");
        foreach (object o in this.m_ExecItemParamList)
            sb.Append(o.ToString()).Append(",");
        sb.Append("
");
        sb.Append("执行时间:").Append(this.m_ExecItemExecTime).Append("
");
        sb.Append("错误信息:").Append(this.ErrMsg).Append("
");
        string mb = sb.ToString();
        //APP.Mail.Send(m_Op + ":" + m_ExecItemClass.Name + "后台处理错", mb, "", BkExecManager.BkManager, "");
    }
}
具体调用方法为

1,首先新调一个后台任务对象.
2,将之加入到任务队列中.

ExecItem ei = new ExecItem(typeof(CacheManager),
    "RefreshObject",
    new object[] { Objtype, Params, ct },
    "缓存刷新",
    "",
    false);  //注意以后可以设置为false,即刷新任务不保存到磁盘,以免影响磁盘性能.

BkExecManager.Execer.AddBkExecItem(ei);

本文作者:朝露绿客联盟 来源:http://www.cnblogs.com/ding0910/
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读