Thursday, May 26, 2011

.NET enigma!

This is a case of a bug fix that I made work, but I can't understand why the solution works. Basically, the story was that some internal component of a third part control forced WPF to throw an exception on the UI thread. As it was impossible to plug the hole in the third party library, and since its next version is supposed to solve the issue, I've opted for a somewhat ugly hack: I've handled the DispatcherUnhandledException event of the Application class and I've basically said to it to ignore that specific UI error.

I will get into details of what the error and where it came from was and how to handle it, but I want to focus on the fact that, since this was a fix for a specific class, I've inherited from that class and used a static method in it to do the above handling of the event. Well, it worked most of the cases, but not all. Some code that involved moving the focus of WPF elements programmatically would cause the bug to reappear.

At first I thought it was a matter of a change in the policy of exception handling from .Net 1.0 to 2.0 and above. So I've set the <legacyUnhandledExceptionPolicy enabled="1"/> option in the app.config runtime section, but it didn't help.

I've tried everything, from using the control instance Dispatcher in the constructor or in the Loaded event, to moving the code directly to the point after the application was instantiated and before the application was run. Bingo, it worked! I thought that was it. I've again encapsulated the entire behavior in the inherited control and ... watched it fail.

Let me simplify the situation: static code that doesn't work when encapsulated in a static class works perfectly when the same code is inlined in the calling code. Can you explain that? I cannot!

The code is simple:

application.DispatcherUnhandledException +=

static void application_DispatcherUnhandledException
(object sender, DispatcherUnhandledExceptionEventArgs e)
if (e.Exception.Message.Contains("Hover")
&& e.Exception.Message
e.Handled = true;

Move that in a static class and execute it as MyClass.RegisterFix(application); and it doesn't catch all the exceptions thrown, although it works in most cases.

Can anyone explain this to me? Why does it matter where the code is?