Windows forms exception handling

Exceptions and Exception Handling (C# Programming Guide)

The C# language’s exception handling features help you deal with any unexpected or exceptional situations that occur when a program is running. Exception handling uses the try , catch , and finally keywords to try actions that may not succeed, to handle failures when you decide that it’s reasonable to do so, and to clean up resources afterward. Exceptions can be generated by the common language runtime (CLR), by .NET or third-party libraries, or by application code. Exceptions are created by using the throw keyword.

In many cases, an exception may be thrown not by a method that your code has called directly, but by another method further down in the call stack. When an exception is thrown, the CLR will unwind the stack, looking for a method with a catch block for the specific exception type, and it will execute the first such catch block that if finds. If it finds no appropriate catch block anywhere in the call stack, it will terminate the process and display a message to the user.

In this example, a method tests for division by zero and catches the error. Without the exception handling, this program would terminate with a DivideByZeroException was unhandled error.

Exceptions Overview

Exceptions have the following properties:

  • Exceptions are types that all ultimately derive from System.Exception .
  • Use a try block around the statements that might throw exceptions.
  • Once an exception occurs in the try block, the flow of control jumps to the first associated exception handler that is present anywhere in the call stack. In C#, the catch keyword is used to define an exception handler.
  • If no exception handler for a given exception is present, the program stops executing with an error message.
  • Don’t catch an exception unless you can handle it and leave the application in a known state. If you catch System.Exception , rethrow it using the throw keyword at the end of the catch block.
  • If a catch block defines an exception variable, you can use it to obtain more information about the type of exception that occurred.
  • Exceptions can be explicitly generated by a program by using the throw keyword.
  • Exception objects contain detailed information about the error, such as the state of the call stack and a text description of the error.
  • Code in a finally block is executed even if an exception is thrown. Use a finally block to release resources, for example to close any streams or files that were opened in the try block.
  • Managed exceptions in .NET are implemented on top of the Win32 structured exception handling mechanism. For more information, see Structured Exception Handling (C/C++) and A Crash Course on the Depths of Win32 Structured Exception Handling.

C# Language Specification

For more information, see Exceptions in the C# Language Specification. The language specification is the definitive source for C# syntax and usage.

Практическое руководство. Обработка ошибок и исключений, происходящих при связывании элементов управления с данными How to: Handle Errors and Exceptions that Occur with Databinding

Зачастую при привязке базовых бизнес-объектов к элементам управления возникают ошибки и исключения. Oftentimes exceptions and errors occur on the underlying business objects when you bind them to controls. Эти ошибки и исключения можно перехватывать, а затем исправлять или передавать сведения об ошибке пользователю путем обработки события BindingComplete для конкретного компонента Binding, BindingSource или CurrencyManager. You can intercept these errors and exceptions and then either recover or pass the error information to the user by handling the BindingComplete event for a particular Binding, BindingSource, or CurrencyManager component.

Пример Example

В данном примере кода показан способ обработки ошибок и исключений, возникающих при выполнении операции привязки данных. This code example demonstrates how to handle errors and exceptions that occur during a data-binding operation. Он демонстрирует перехват ошибок путем обработки события Binding.BindingComplete объектов Binding. It demonstrates how to intercept errors by handling the Binding.BindingComplete event of the Binding objects. Для перехвата ошибок и исключений с помощью обработки этого события необходимо включить поддержку форматирования для привязки. In order to intercept errors and exceptions by handling this event, you must enable formatting for the binding. Форматирование можно включить при создании привязки или добавлении в коллекцию привязок, или установив значение свойства FormattingEnabled равным true . You can enable formatting when the binding is constructed or added to the binding collection, or by setting the FormattingEnabled property to true .

Читайте также:  Обзоры операционных систем linux

Во время выполнения, если введена пустая строка в качестве имени или значение меньше 100 в качестве числа, то появится окно с сообщением. When the code is running and an empty string is entered for the part name or a value less than 100 is entered for the part number, a message box appears. Это происходит в результате обработки события Binding.BindingComplete для привязок этих текстовых полей. This is a result of handling the Binding.BindingComplete event for these textbox bindings.

Компиляция кода Compiling the Code

Для этого примера требуются: This example requires:

Top-level Exception Handling in Windows Forms Applications – Code Listing 1

This is a very basic code example of how to use the ThreadException event to handle exceptions occurring anywhere on the main GUI thread in a Windows Forms application. My blog article ‘Top-level Exception Handling in Windows Forms Applications’ discusses this in more detail.

From looking at the forums it seems many people have problems getting the ThreadException event to fire correctly. To make sure you can get my example working I have included quite detailed instructions: you probably don’t need these though!

1. Create a new C# Windows Application in Visual Studio 2005, calling it ExceptionHandling1.

2. Replace the code in Program.cs with the code below.

using System . Windows . Forms ;

using System . Threading ;

static class Program

/// The main entry point for the application.

static void
Main ()

Application . ThreadException += new ThreadExceptionEventHandler ( new ThreadExceptionHandler (). ApplicationThreadException );

Application . Run ( new Form1 ());

/// Handles any thread exceptions

public class ThreadExceptionHandler

public void ApplicationThreadException ( object sender , ThreadExceptionEventArgs e )

MessageBox . Show ( e . Exception . Message , “An exception occurred:” , MessageBoxButtons . OK , MessageBoxIcon . Error );

3. Replace the code behind the default Form1 with the code below (Form1.cs):

using System . Windows . Forms ;

using System . Threading ;

public partial class Form1 : Form

private void throwExceptionButton_Click ( object sender , EventArgs e )

private void ThrowException ()

// Note that in general you shouldn’t throw a generic ApplicationException

// but should use a more specific exception class derived from it

throw new ApplicationException ( “Monkey exception” );

private void exceptionOnNewFormButton_Click ( object sender , EventArgs e )

Form1 form = new Form1 ();

4. Replace the code in Form1.Designer.cs with the code below:

partial class Form1

/// Required designer variable.

private System . ComponentModel . IContainer components = null ;

/// Clean up any resources being used.

true if managed resources should be disposed; otherwise, false.

protected override void Dispose ( bool disposing )

if ( disposing && ( components != null ))

base . Dispose ( disposing );

#region Windows Form Designer generated code

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

private void InitializeComponent ()

this . throwExceptionButton = new System . Windows . Forms . Button ();

this . newFormButton = new System . Windows . Forms . Button ();

this . throwExceptionButton . Location = new System . Drawing . Point (12, 12);

this . throwExceptionButton . Name = “throwExceptionButton” ;

this . throwExceptionButton . Size = new System . Drawing . Size (75, 51);

this . throwExceptionButton . TabIndex = 0;

this . throwExceptionButton . Text = “Throw Exception” ;

this . throwExceptionButton . UseVisualStyleBackColor = true ;

this . throwExceptionButton . Click += new System . EventHandler ( this . throwExceptionButton_Click );

this . newFormButton . Location = new System . Drawing . Point (93, 12);

this . newFormButton . Name = “newFormButton” ;

this . newFormButton . Size = new System . Drawing . Size (75, 51);

this . newFormButton . TabIndex = 2;

this . newFormButton . Text = “New Form” ;

this . newFormButton . UseVisualStyleBackColor = true ;

this . newFormButton . Click += new System . EventHandler ( this . exceptionOnNewFormButton_Click );

this . AutoScaleDimensions = new System . Drawing . SizeF (6F, 13F);

this . AutoScaleMode = System . Windows . Forms . AutoScaleMode . Font ;

this . ClientSize = new System . Drawing . Size (202, 79);

this . Controls . Add ( this . newFormButton );

this . Controls . Add ( this . throwExceptionButton );

Читайте также:  Windows app boss rus

this . Name = “ExceptionHandlingForm” ;

this . Text = “Exception Handling” ;

this . ResumeLayout ( false );

private System . Windows . Forms . Button throwExceptionButton ;

private System . Windows . Forms . Button newFormButton ;

5. Run this code. If you run the code in debug, when you hit the ‘Throw Exception’ button the code will break saying that an exception has occurred (unless you’ve disabled this). If you now hit F5 to continue you will see that the top-level exception handler is being called. If you run the code by double-clicking ExceptionHandling1.exe you will see that the top-level exception handler has been called directly.

Exception handling with multiple forms

I’m seeing different behavior with exceptions being caught or not being caught when I am debugging vs. when I am running a compiled .exe. I have two forms (Form1 and Form2). Form1 has a button on it which instantiates and calls ShowDialog on Form2. Form2 has a button on it which intentionally produces a divide by zero error. When I’m debugging, the catch block in Form1 is hit. When I run the compiled .exe, it is NOT hit, and instead I get a message box that states, «Unhandled exception has occurred in your application. If you click continue, the application will ignore this error and attempt to continue. If you click Quit, the application will close immediately. Attempted to divide by zero». My question is why do you get different behavior when debugging vs. when running the .exe? If that is the expected behavior, then would it be considered necessary to put try/catch blocks in every single event handler? That seems kind of crazy over kill, doesn’t it?

Here’s the code for Form1.

Here’s Form2’s code:

2 Answers 2

I get the same behaviour as you. I don’t know why this happens, but it seems to be a bad idea to assume that an exception generated from an event in a form will appear on the stack of the ShowDialog() call. It would be better to do these two things:

  • Catch and handle the exceptions in the event handlers in Form2 where it makes sense to do so, and when you can do something meaningful with the exception.
  • Add an unhandled exception handler (`Application_ThreadException`) for your entire application to catch any unhandled exceptions.

Update: Here are the stack traces. Debug version:

Notice that System.Windows.Forms.Form.ShowDialog() is not in the stack trace in release mode, which is why your try <> catch <> does nothing. Also notable is that in the debug case it is using NativeWindow.DebuggableCallback which is presumably designed to help debugging by not breaking the stack, whereas in Release mode is uses NativeWindow.Callback .

Yes, this is by design and is closely associated with the way Windows Forms works. In a Winforms app, code runs in response to messages posted to the active window by Windows. Every native Windows app contains a message loop to detect these messages. The Winforms plumbing ensures one of your event handlers runs in response; button1_Click in your example code.

Most Winforms controls implement their own event handlers. A PictureBox for example has a Paint event handler that ensures its Image is drawn to the screen. This is all done automatically, you don’t have to write any code yourself to make this work.

There is however a problem when this code throws an exception, there is no way for you to catch such an exception since none of your own code was involved. In other words, there is no place for you to inject your own try block. The very last bit of your own program’s code that was involved is the code that got the message loop started. The Application.Run() method call, normally in Program.cs. Or the Form.ShowDialog() call if you display a dialog. Either of those methods start a message loop. Putting a try block around the Application.Run() call isn’t useful, the app will terminate after catching an exception.

To combat this problem, the Winforms message loop code contains a try block around the code that dispatches an event. Its catch clause displays the dialog you mentioned, it is implemented by the ThreadExceptionDialog class.

Getting to the point of your question: this catch clause really gets in the way of troubleshooting problems with your code when you debug. The debugger will only stop on an exception when there is no catch block that handles the exception. But when your code throws an exception, you’ll want to know about it when you debug. The previously mentioned code in the message loop is aware whether or not a debugger is attached. If it is, it dispatches events without the try/catch block. Now, when your code throws an exception, there is no catch clause to handle it and the debugger will stop the program, giving you a chance to find out what went wrong.

Читайте также:  Codecs all in one linux

Perhaps you see now why your program behaves the way it does. When you debug, the catch clause in the message loop is disabled, giving the catch clause in the Form1 code a chance to catch the exception. When you don’t, the message loop catch clause handles the exception (by displaying the dialog) and prevents the exception from unwinding to the Form1 code.

Application. Thread Exception Событие

Определение

Происходит при выдаче неперехваченного исключения потока. Occurs when an untrapped thread exception is thrown.

Тип события

Примеры

В следующем примере кода задаются обработчики событий для исключений, происходящих в Windows Forms потоках и исключениях, происходящих в других потоках. The following code example sets event handlers for exceptions that occur on Windows Forms threads and exceptions that occur on other threads. Он устанавливает SetUnhandledExceptionMode так, чтобы все исключения обрабатывались приложением, независимо от параметров в файле конфигурации пользователя приложения. It sets SetUnhandledExceptionMode so that all exceptions are handled by the application, regardless of the settings in the application’s user configuration file. Он использует ThreadException событие для обработки исключений потока пользовательского интерфейса, а UnhandledException событие — для обработки исключений потока, не относящегося к ПОЛЬЗОВАТЕЛЬСКОМу интерфейсу. It uses the ThreadException event to handle UI thread exceptions, and the UnhandledException event to handle non-UI thread exceptions. Поскольку UnhandledException не может препятствовать завершению работы приложения, в примере просто записывается ошибка в журнал событий приложения перед завершением работы. Since UnhandledException cannot prevent an application from terminating, the example simply logs the error in the application event log before termination.

В этом примере предполагается, что Button в классе определены два элемента управления button1 и button2 Form . This example assumes that you have defined two Button controls, button1 and button2 , on your Form class.

Комментарии

Это событие позволяет Windows Formsному приложению обрабатывать необработанные исключения, происходящие в потоках Windows Forms. This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads. Присоедините обработчик событий к ThreadException событию, чтобы обработать эти исключения, что приведет к неизвестному состоянию приложения. Attach your event handler to the ThreadException event to deal with these exceptions, which will leave your application in an unknown state. Там, где это возможно, исключения должны обрабатываться блоком структурированной обработки исключений. Where possible, exceptions should be handled by a structured exception handling block.

Можно изменить, используется ли этот обратный вызов для необработанных Windows Forms исключений потоков, установив SetUnhandledExceptionMode . You can change whether this callback is used for unhandled Windows Forms thread exceptions by setting SetUnhandledExceptionMode. Чтобы перехватить исключения, происходящие в потоках, не созданных и не принадлежащих Windows Forms, используйте UnhandledException обработчик событий. To catch exceptions that occur in threads not created and owned by Windows Forms, use the UnhandledException event handler.

Чтобы гарантировать отсутствие активации этого события, необходимо присоединить обработчик перед вызовом метода Application.Run . To guarantee that no activations of this event are missed, you must attach a handler before you call Application.Run.

К этому событию можно прикрепить только один обработчик. Only one handler can be attached to this event. Если добавлено несколько обработчиков, для необработанного исключения будет вызван только самый последний добавленный обработчик. If multiple handlers are added, only the most recently added handler will be called on an unhandled exception.

Поскольку это статическое событие, необходимо отсоединить обработчики событий при удалении приложения или привести к утечке памяти. Because this is a static event, you must detach your event handlers when your application is disposed, or memory leaks will result.

Оцените статью