隨筆-6  評論-2  文章-0  trackbacks-0
          ASP.net 的后臺處理技術 

          轉自:http://www.chenjiliang.com/Article/View.aspx?ArticleID=3636&TypeID=5

          使用方法:
          System.Threading.TimerCallback t=new System.Threading.TimerCallback (你的處理方法);
          System.Threading.Timer t 
          = new System.Threading.Timer(t,null,1000,5000);

          在具體實現時我定義了三個類。
          1、BkExecItem用于保存用戶提交操作,同時它也可以序列化到磁盤上,以免關鍵后臺任務丟失。

          2、BkExec用于執行。它通過反射來調用BkExecItem中所指定的方法。另外它中間還維護一個先入

          先出隊列Queue<BkExecItem>,這個隊列記錄全部的后臺處理項。

          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, null5000, 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, 
                              
          nullnull, 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);

          posted on 2008-02-28 13:28 vls 閱讀(648) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 宜都市| 灌云县| 井陉县| 刚察县| 金昌市| 泉州市| 高陵县| 应城市| 蓬溪县| 天津市| 固安县| 林州市| 册亨县| 会宁县| 莎车县| 穆棱市| 新昌县| 建昌县| 河北区| 麻江县| 永泰县| 高雄县| 芦山县| 新密市| 辽源市| 北京市| 常德市| 朝阳市| 沈丘县| 金秀| 衢州市| 电白县| 彰化市| 远安县| 通山县| 三穗县| 阿瓦提县| 大洼县| 大兴区| 巨鹿县| 颍上县|