一個實用ASP.Net 幕後處理類

來源:互聯網
上載者:User
呵.這回跟大家討論下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);

        }

        /// <summary>
        /// 停止定時器.
        /// </summary>
        static void BkExecQuit()
        {
            stateTimer.Dispose();
        }
    }

2,幕後處理執行
public class BkExecer
    {
        //維護一
個前進前出的隊列。
        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);

            ////讀入待處理事項
            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]
    /// <summary>
    /// 後台命令集合
    /// 直接將這些後台命令二進位序列化到WEb伺服器上儲存。
    /// 如果完成後則從Web伺服器上刪除。
    /// 如果異常則發郵件通知管理員。
    /// </summary>
    public class ExecItem
    {
        /// <summary>
        /// 磁碟文檔名稱 。
        /// </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>
        /// 背景工作對象
        /// </summary>
        /// <param name="objtype">物件類型</param>
        /// <param name="ExecMethod">調用方法</param>
        /// <param name="param">調用參數</param>
        /// <param name="ExecName">任務名</param>
        /// <param name="Op">提交人</param>
        /// <param name="SavetoDisk">是否儲存到磁碟</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.待執行;
            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("<BR>");
            sb.Append("提交時間:").Append(this.ExecItemCreateTime).Append("<BR>");
            sb.Append("對象:").Append(this.m_ExecItemClass.Name).Append("<BR>");
            sb.Append("方法:").Append(this.m_ExecItemMethed).Append("<BR>");
            sb.Append("參數:");
            foreach (object o in this.m_ExecItemParamList)
                sb.Append(o.ToString()).Append(",");
            sb.Append("<BR>");
            sb.Append("執行時間:").Append(this.m_ExecItemExecTime).Append("<BR>");
            sb.Append("錯誤資訊:").Append(this.ErrMsg).Append("<BR>");
            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);

現在這個對象在我們項目中運行良好.

後期還想繼續完善這個對象.它現在的不足有 :沒有讓使用者知道他提交的操作執行進度,操作結果等.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.