Why is my exception being swallowed in my Form’s Load handler?
So, you’ve got a WinForms app and you expect an exception to be thrown within your Form’s Load handler. Maybe you even deliberately throw one yourself. But when you start debugging, the execution of your Load handler terminates at the point where the exception was thrown, but no exception is reported and your application keeps running!
This issue was baffling me for several hours today when a colleague of mine pointed me to a helpful post at StackOverflow that explains the problem.
If these conditions are met:
- You are running on a 64-bit version of Windows (whether your application is built for 32-bit or 64-bit doesn’t matter; only the bit depth of the OS)
- You are building a WinForms app
- You are debugging the application with Visual Studio (using default options for Exception catching)
- Your main form has a Load event handler
- During the execution of your Load handler, an exception occurs
Then:
The exception will be silently swallowed by the system and, while your handler will not continue execution, your application will continue running.If you wrap your handler code in a try/catch block, you can still explicitly catch any thrown exceptions. But if you don’t, you’ll never know anything went wrong.
Note that all of the conditions must be met. If, for instance, you run the application without debugging, then an unhandled exception still be correctly thrown.
According to this Microsoft Connect post, this has been a known issue with 64-bit Windows since 2008:
This is a known issue on 64-bit OS platform. The reason is that the 64bit OS core does not allow user mode exception through kernal mode stacks. The exception is swallowed by OS sliently. That happens in FormLoad handler, because it is called in an OS callback. 32bits OS doesn't do this, so it doesn't repro there.
Paul Betts sheds more technical light on what’s going on, although I believe his post addresses the swallowing of such exceptions even without debugging, something that is supposed to have been resolved for Windows 7 SP1.
Workarounds
If you need the debugger to break during your load method, there are a few things you can do:
Break whenever a CLR Exception is thrown
You can optionally tell Visual Studio to break whenever a CLR exception is thrown, even if it normally would have later been caught (via Debug… Exceptions… or Ctrl+Alt+E).
The downside to this approach is that you may see a lot of “noise” about thrown exceptions that are eventually handled (although in some circumstances this is an invaluable tool to discover exceptions that are being thrown that shouldn’t be).
You can catch exceptions in the other categories as well, but typically it’s the CLR exceptions you’ll be interested in.
Use the Application.ThreadException Handler as a Breakpoint
You can attach a handler to the Application.ThreadException event before running your app, and you can set a breakpoint within it to inspect the original exception that was thrown.
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.ThreadException += (o, args) =>
{
var x = args.Exception; //Set breakpoint here to inspect args.Exception
};
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
The downside to this approach is that you can get into this handler for all sorts of other things as well. But if you’re just trying to see what’s being thrown during startup, this will do it.
Use a 32-bit Version of Windows
Yeah, it’s drastic, but if you’ve got VMs or other machines available, you can always debug on a 32-bit version of Windows.
