1、 基本原则:不要轻易捕获根异常;
2、 组件或控件抛出异常时可以根据需要自定义一些异常,不要抛出根异常,可以直接使用的常用异常有:FormatException、IndexOutOfRangException、InvalidOperationException、InvalidEnumArgumentException ;没有合适的就自定义;
3、 用户自定义异常从ApplicationException继承;
4、 多线程的内部异常不会传播到主线程,应该在内部进行处理,可以通过事件推到主线程来;
5、应用程序层面可以捕获根异常,做一些记录工作,切不可隐匿异常。
捕获你知道的异常,并自行处理,但不要轻易捕获根异常,下面的代码令人深恶痛绝:
————————————————
版权声明:本文为CSDN博主「kalvin_y_liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kalvin_y_liu/article/details/127479415
解释一下:
1、 当主线程发生未处理异常时会触发App_DispatcherUnhandledException事件,在该事件中如果设置e.Handled = true,那么系统不会崩溃,如果没有设置e.Handled = true,会继续触发CurrentDomain_UnhandledException事件(毕竟主线程也是线程),而CurrentDomain_UnhandledException事件和TaskScheduler_UnobservedTaskException事件触发后,操作系统都会强行关闭这个应用程序。所以我们应该在App_DispatcherUnhandledException事件中设置e.Handled = true。
2、Thread线程异常会触发CurrentDomain_UnhandledException事件,导致系统崩溃,所以建议尽量不要使用Thread和ThreadPool。
3、非可等待的Task内部异常会触发TaskScheduler_UnobservedTaskException事件,导致系统崩溃,所以建议Task内部自行处理根异常或将异常封装为事件推到主线程。需要额外注意一点:Task内的未处理异常不会被立即触发事件,而是要延迟到GC执行回收的时候才触发,这使得问题更复杂,需要小心处理。
————————————————
版权声明:本文为CSDN博主「kalvin_y_liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kalvin_y_liu/article/details/127479415
在发生未捕获线程异常时发生。
public static event System.Threading.ThreadExceptionEventHandler ThreadException;
下面的代码示例为Windows 窗体线程上发生的异常和在其他线程上发生的异常设置事件处理程序。
它设置 SetUnhandledExceptionMode ,以便应用程序处理所有异常,而不管应用程序的用户配置文件中的设置如何。
它使用 ThreadException 事件来处理 UI 线程异常,以及 UnhandledException 用于处理非 UI 线程异常的事件。
由于 UnhandledException 无法阻止应用程序终止,示例只需在终止前记录应用程序事件日志中的错误。
此示例假定你已定义两 Button 个控件, button1 并在 button2类上定义了两个 Form 控件。
Thread newThread = null;
// Starts the application.
public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// Runs the application.
Application.Run(new ErrorHandlerForm());
}
// Programs the button to throw an exception when clicked.
private void button1_Click(object sender, System.EventArgs e)
{
throw new ArgumentException("The parameter was invalid");
}
// Start a new thread, separate from Windows Forms, that will throw an exception.
private void button2_Click(object sender, System.EventArgs e)
{
ThreadStart newThreadStart = new ThreadStart(newThread_Execute);
newThread = new Thread(newThreadStart);
newThread.Start();
}
// The thread we start up to demonstrate non-UI exception handling.
void newThread_Execute()
{
throw new Exception("The method or operation is not implemented.");
}
// Handle the UI exceptions by showing a dialog box, and asking the user whether
// or not they wish to abort execution.
//通过显示对话框并询问用户是否或者他们不希望中止执行。
private static void Form1_UIThreadException(object sender, ThreadExceptionEventArgs t)
{
DialogResult result = DialogResult.Cancel;
try
{
result = ShowThreadExceptionDialog("Windows Forms Error", t.Exception);
}
catch
{
try
{
MessageBox.Show("Fatal Windows Forms Error",
"Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
}
finally
{
Application.Exit();
}
}
// Exits the program when the user clicks Abort.
if (result == DialogResult.Abort)
Application.Exit();
}
// Handle the UI exceptions by showing a dialog box, and asking the user whether or not they wish to abort execution.
// NOTE: This exception cannot be kept from terminating the application - it can only
// log the event, and inform the user about it.
//通过显示对话框并询问用户是否或者他们不希望中止执行。
//注意:不能阻止此异常终止应用程序-它只能记录事件并通知用户。
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = (Exception)e.ExceptionObject;
string errorMsg = "An application error occurred. Please contact the adminstrator " +
"with the following information:\n\n";
// Since we can't prevent the app from terminating, log this to the event log.
if (!EventLog.SourceExists("ThreadException"))
{
EventLog.CreateEventSource("ThreadException", "Application");
}
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "ThreadException";
myLog.WriteEntry(errorMsg + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace);
}
catch (Exception exc)
{
try
{
MessageBox.Show("Fatal Non-UI Error",
"Fatal Non-UI Error. Could not write the error to the event log. Reason: "
+ exc.Message, MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
Application.Exit();
}
}
}
// Creates the error message and displays it.
private static DialogResult ShowThreadExceptionDialog(string title, Exception e)
{
string errorMsg = "An application error occurred. Please contact the adminstrator " +
"with the following information:\n\n";
errorMsg = errorMsg + e.Message + "\n\nStack Trace:\n" + e.StackTrace;
return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore,
MessageBoxIcon.Stop);
}