.NET - ما هي أفضل طريقة لتنفيذ "معالج التقاط كافة الاستثناءات"

StackOverflow https://stackoverflow.com/questions/219594

سؤال

أنا أتساءل ما هي أفضل طريقة للحصول على "إذا فشل كل شيء آخر في الإمساك به".

أعني ، أنت تتعامل مع أكبر قدر ممكن من الاستثناءات في تطبيقك ، ولكن لا يزال هناك حدود لخطأ ، لذلك أحتاج إلى الحصول على شيء يمسك بجميع الاستثناءات غير المعقولة حتى أتمكن من جمع المعلومات وتخزينها في قاعدة بيانات أو إرسالها إلى خدمة الويب.

هل يلتقط حدث AppDomain.CurrentDomain.UnhandledException كل شيء؟حتى لو كان التطبيق متعدد الخيوط؟

ملاحظة جانبية:Windows Vista يعرض وظائف واجهة برمجة التطبيقات الأصلية التي تسمح لأي تطبيق باسترداد نفسه بعد تعطل ...لا أستطيع التفكير في الاسم الآن..لكنني أفضل عدم استخدامه ، حيث لا يزال العديد من مستخدمينا يستخدمون Windows XP.

هل كانت مفيدة؟

المحلول

لقد لعبت للتو مع سلوك AppDomain Unhandledexception ، (هذه هي المرحلة الأخيرة التي يتم تسجيل الاستثناء غير المعدل في)

نعم، بعد معالجة معالجات الأحداث، سيتم إنهاء طلبك وسيظهر "..."توقف البرنامج عن العمل" يظهر الحوار.

:) أنت ما زال يمكن تجنب ذلك.

الدفع:

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

ملاحظة. قم بالتعامل مع التطبيقات غير المعالجة لـ Application.ThreadException (WinForms) أو DispatcherUnhandledException (WPF) في المستوى الأعلى.

نصائح أخرى

في ASP.NET، يمكنك استخدام وظيفة Application_Error في ملف Global.asax.

في WinForms عناصر، يمكنك استخدام MyApplication_UnhandledException في ملف ApplicationEvents

ويتم استدعاء كلا من هذه الوظائف إذا حدث استثناء غير معالج في التعليمات البرمجية. يمكنك تسجيل الاستثناء وتقديم رسالة لطيفة للمستخدم من هذه الوظائف.

لتطبيقات Winform، بالإضافة إلى AppDomain.CurrentDomain.UnhandledException أنا أيضا استخدام <لأ href = "http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx "يختلط =" noreferrer "> Application.ThreadException و <لأ href =" http://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode.aspx "يختلط = "noreferrer"> Application.SetUnhandledExceptionMode (ث / UnhandledExceptionMode.CatchException). ويبدو أن هذا الجمع للقبض على كل شيء.

في الموضوع الرئيسي، لديك الخيارات التالية:

لموضوعات أخرى:

  • لا تحتوي مؤشرات الترابط الثانوية على استثناءات غير معالجة؛يستخدم موضوع آمن
  • خيوط العامل:(المؤقت، Threadpool) لا توجد شبكة أمان على الإطلاق!

ضع في اعتبارك أن هذه الأحداث لا تفعل ذلك مقبض استثناءات، فهي مجرد تقرير إلى التطبيق - غالبًا عندما يكون الوقت قد فات لفعل أي شيء مفيد/عاقل بشأنهم

استثناءات التسجيل جيدة، لكن مراقبة التطبيقات أفضل ;-)

تنبيه قضائي:أنا مؤلف كتاب موضوع آمن شرط.

لWinForms عناصر، لا تنسى أن نعلق على الحدث استثناء غير معالج في الموضوع الحالي جدا (خاصة إذا كنت تستخدم خيوط متعددة).

وبعض الوصلات على أفضل الممارسات هنا و <لأ href = "http://dturini.blogspot.com/2005/02/exception-handling-best-practices-in.html" يختلط = "نوفولو noreferrer"> هنا و <لأ href = "HTTP: // شبكة الاتصالات العالمية .codeproject.com / مقالات / 9538 / معالجة الاستثناءات-أفضل الممارسات في وNET "يختلط =" نوفولو noreferrer "> هنا (ربما أفضل مقال معالجة الاستثناء ل. NET)

هناك أيضًا شيء رائع يسمى إلماه سيؤدي ذلك إلى تسجيل أي أخطاء ASP.NET تحدث في تطبيق الويب.أعلم أنك تسأل عن حل Winform App، ولكنني شعرت أن هذا قد يكون مفيدًا لأي شخص يحتاج إلى هذا النوع من الأشياء على تطبيق ويب.نحن نستخدمه حيث أعمل وكان مفيدًا جدًا في تصحيح الأخطاء (خاصة على خوادم الإنتاج!)

إليك بعض الميزات التي يحتوي عليها (تم سحبها مباشرة من الصفحة):

  • تسجيل جميع الاستثناءات التي لم تتم معالجتها تقريبًا.
  • صفحة ويب لعرض السجل الكامل للاستثناءات المعاد ترميزها عن بعد.
  • صفحة ويب لعرض التفاصيل الكاملة لأي استثناء مسجل عن بعد.
  • في كثير من الحالات ، يمكنك مراجعة الشاشة الصفراء الأصفر من الموت الذي تم إنشاؤه لاستثناء معين ، حتى مع إيقاف تشغيل وضع CustomerRors.
  • إشعار عبر البريد الإلكتروني بكل خطأ وقت حدوثه.
  • موجز RSS لآخر 15 خطأ من السجل.
  • عدد من تطبيقات تخزين الدعم للسجل ، بما في ذلك الذاكرة ، خادم Microsoft SQL والعديد من المجتمع الذي ساهم به المجتمع.

ويمكنك مراقبة معظم استثناءات في هذا المعالج حتى في تطبيقات متعددة الخيوط، ولكن صافي (بدءا 2.0) لا تسمح لك لإلغاء الاستثناءات غير المعالجة إلا إذا تمكن من وضع 1.1 التوافق. وعندما يحدث ذلك سيتم إيقاف في AppDomain أسفل مهما كانت. وأفضل ما يمكن القيام به هو إطلاق التطبيق في AppDomain مختلفة بحيث يمكنك التعامل مع هذا الاستثناء وإنشاء AppDomain جديد لإعادة تشغيل التطبيق.

وأنا باستخدام النهج التالي، والذي يعمل ويقلل كثيرا من كمية من التعليمات البرمجية (أنا لست متأكدا مما إذا كان هناك طريقة أفضل أو ما مزالق قد يكون. كلما الاتصال على: أنا quess وquys إعطاء السلبيات أن يكون مهذبا بما فيه الكفاية لتوضيح أفعالهم؛ )

try 
{
    CallTheCodeThatMightThrowException()
 }
catch (Exception ex)
{
    System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
    Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch

وهنا هو رمز ErrorHandler: فقط لجعل clear-: objUser - هو الكائن نمذجة appusers (قد تحصل على معلومات مثل اسم النطاق، وإدارة، والمنطقة وما إلى ذلك لأغراض التسجيل ILOG مسجل - هو كائن قطع الأشجار - على سبيل المثال واحد أداء أنشطة قطع الأشجار تتبع مكدس الذاكرة المؤقتة الحادي و- الكائن تتبع مكدس الذاكرة المؤقتة مما يتيح لك تصحيح المعلومات عن تطبيقك

using System;
using log4net; //or another logging platform

namespace GenApp.Utils
{
  public class ErrorHandler
  {
    public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
    {
      if (ex is NullReferenceException)
      { 
      //do stuff for this ex type
      } //eof if

      if (ex is System.InvalidOperationException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.IndexOutOfRangeException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.Data.SqlClient.SqlException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.FormatException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is Exception)
      {
        //do stuff for this ex type
      } //eof catch

    } //eof method 

  }//eof class 
} //eof namesp

في التطبيق واجهة المستخدم الرسومية يدار بشكل افتراضي، يتم التعامل مع الاستثناءات التي تنشأ في موضوع واجهة المستخدم الرسومية التي مهما تم تعيينه إلى Application.ThreadException.

يتم التعامل مع

والاستثناءات التي تنشأ في المواضيع الأخرى التي AppDomain.CurrentDomain.UnhandledException.

إذا كنت تريد استثناءات موضوع GUI الخاص للعمل تماما مثل الخاص بك غير تلك التي واجهة المستخدم الرسومية، بحيث تحصل على التعامل معها من قبل AppDomain.CurrentDomain.UnhandledException، يمكنك القيام بذلك:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

وميزة لاصطياد الاستثناءات موضوع واجهة المستخدم الرسومية باستخدام ThreadException هي التي يمكن أن تعطي استخدام خيارات السماح يستمر التطبيق. للتأكد من عدم وجود ملفات التكوين وتجاوز السلوك الافتراضي، يمكنك الاتصال على:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

وأنت لا تزال عرضة للاستثناءات من دلس الأم تصرفت بشكل سيئ. إذا دلل الأصلي تثبيت معالج الخاصة به باستخدام Win32 SetUnhandledExceptionFilter، أنه من المفترض أن حفظ المؤشر إلى تصفية السابق والذي يطلق عليه أيضا. اذا لم نفعل ذلك، معالج الخاص بك لن 'الحصول على استدعاء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top