ASP.NET MVC自定義異常處理

1.自定義異常處理過濾器類文件html

新建MyExceptionAttribute.cs異常處理類文件數據庫

MyExceptionAttribute.cs代碼以下:安全

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApp.Models
{
    public class MyExceptionAttribute : HandleErrorAttribute
    {
        public static Queue<Exception> exceptionQueue = new Queue<Exception>(); //異常處理隊列對象 /// <summary>
        /// 控制器方法中出現異常,會調用該方法捕獲異常
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnException(ExceptionContext filterContext)
        {
            exceptionQueue.Enqueue(filterContext.Exception);//將捕獲的異常信息寫到隊列中

            filterContext.HttpContext.Response.Redirect("/Error.html");//跳轉到錯誤頁面

            base.OnException(filterContext);
        }

    }
}

 

2.將錯誤處理過濾器修改成自定義的異常處理過濾器服務器

修改以下:併發

using System.Web;
using System.Web.Mvc;
using WebApp.Models;

namespace WebApp
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());
            filters.Add(new MyExceptionAttribute());//使用自定義異常處理的過濾器
        }
    }
}

 

3.修改Global.asax文件,在程序首次加載的時候,開啓線程掃描異常隊列,處理異常信息ide

using Spring.Web.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using WebApp.Models;

namespace WebApp
{
    // 注意: 有關啓用 IIS6 或 IIS7 經典模式的說明,
    // 請訪問 http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : SpringMvcApplication //System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            #region 開啓線程掃描異隊列,處理異常信息
            string fileLogPath = Server.MapPath("/Log/");//知道用來保存錯誤日誌文件的文件夾路徑
            //開啓一個線程掃描日誌隊列
            ThreadPool.QueueUserWorkItem((a) =>
            {
                while (true)
                {
                    if (MyExceptionAttribute.exceptionQueue.Count > 0) //判斷隊列中是否有數據
                    {
                        Exception ex = MyExceptionAttribute.exceptionQueue.Dequeue();//出隊
                        if (ex != null)
                        {
                            string fileName = DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                            File.AppendAllText(fileLogPath + fileName, ex.ToString(), Encoding.Default);//將異常追加寫入到文件中
                        }
                        else
                        {
                            Thread.Sleep(3000);
                        }
                    }
                    else
                    {
                        Thread.Sleep(3000);//若是隊列中沒有數據,讓當前線程休息3秒鐘,避免形成CPU空轉,避免CPU的浪費
                    }
                }
            }, fileLogPath);
            #endregion


        }
    }
}

 

4.測試:高併發

   public ActionResult Index()
        {
            int a = 2;
            int b = 0;
            int c = a / b;
            return Content(c.ToString());
        }

 

5.效果性能

 

6.其餘說明:測試

1.解決高併發錯誤日誌問題:
   1.1用傳統lock方式,若是併發量很大的話,用戶會出現卡頓的狀況。
   1.2.在服務器開闢一個隊列,存儲用戶錯誤信息,而後單獨開啓一個線程來處理,就不會有卡頓狀況。(隊列是在內存中,寫入速度很快)
   這就是生產者消費者模式

2.Global下Application_Start()方法只在程序首次執行時調用

3.ThreadPool線程池線程性能很好,比咱們本身建立線程的效率要高不少。

4.池用來解決對象頻繁建立的問題,頻繁建立消耗性能。

5.Queue自己不是線程安全的,作下面的處理後就能夠保證是線程內安全的了,就不會出現併發問題。spa

Queue queue = Queue.Synchronized(myQueue); 

 

7.源碼下載:

點擊下載源碼>>

點擊下載數據庫文件>>

相關文章
相關標籤/搜索