۱۳۸۷/۱۰/۱۴

به دام انداختن خطاهاي مديريت نشده در برنامه‌هاي Windows forms دات نت


شبيه به نحوه‌ي به دام انداختن خطاهاي مديريت نشده در Web forms و روال استاندارد Application_Error ، در برنامه‌هاي Windows forms نيز اين امر به صورت زير ممكن است:


using System;
using System.Threading;
using System.Windows.Forms;

namespace testWinForms87
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// handling UI thread exceptions
Application.ThreadException += uIThreadException;

// force all Windows Forms errors to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// handling non-UI thread exceptions.
AppDomain.CurrentDomain.UnhandledException += currentDomainUnhandledException;


Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

private static void currentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(((Exception)e.ExceptionObject).Message, "currentDomainUnhandledException");
}

private static void uIThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "uIThreadException");
}
}
}

چند نكته:
الف)همانطور كه ملاحظه مي‌كنيد سطرهاي فوق بايد قبل از Application.Run در روال اصلي برنامه تعريف شوند.
ب) اين متدها استاتيك هستند و توصيه شده است در پايان برنامه ارجاعات آنها را حذف كنيد تا نشتي حافظه رخ ندهد. دقيقا به همين صورت =+ كه اضافه شدند با =- هم قابل حذف هستند.
ج) در حالت اجرا شدن uIThreadException ، برنامه بسته نخواهد شد (و بديهي است در صورت عدم بكار گيري اين روش، حتما برنامه كرش خواهد كرد). براي مثال شايد علاقمند نباشيد كه بخاطر عدم دسترسي نوشتن در پوشه‌اي خاص، خطاي حاصل سبب بسته شدن كل برنامه شود. به اين صورت اين موارد را مي‌توان به دام انداخت. اما currentDomainUnhandledException كه حاصل از خطاهاي ايجاد شده براي مثال در يك ترد ديگر بجز ترد اصلي برنامه هستند، حتما سبب بسته شدن برنامه خواهند شد. بنابراين اينجا تنها شانس لاگ كردن خطاي مديريت نشده حاصل را خواهيم داشت. به همين منظور هميشه توصيه مي‌شود كه در تردهاي ايجاد شده در برنامه، حتما موارد مديريت خطاها را لحاظ نمائيد، زيرا خطاهاي حاصل شده در آن‌ها غيرقابل اغماض بوده و حتما سبب كرش برنامه مي‌شوند.

پ.ن.
دقيقا در برنامه‌هاي Win32 دلفي هم چنين قابليتي به همين شكل و تقريبا با همين نام‌ها وجود دارد. فقط كافي است روالي را جهت Application.OnException ايجاد كنيد: ;)

procedure TmyFrmMain.FormCreate(Sender: TObject);
begin
Application.OnException := MyExceptionHandler;
end;
procedure TmyFrmMain.MyExceptionHandler(Sender: TObject; E: Exception);
begin
ShowMessage(e.Message);
end;