4

I don't understand why I only get 1 Message Box in the following case when I run using (CTRL-F5 - Run Without Debugger) in VS2010:

Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ' Add the event handler for handling UI thread exceptions to the event.
        AddHandler Application.ThreadException, AddressOf ThreadExceptionHandler
        AddHandler Application.ThreadException, AddressOf ThreadExceptionHandler2

        Throw New Exception("Ha!")

    End Sub

    Private Sub ThreadExceptionHandler(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
        MsgBox("FirstHandler")
    End Sub

    Private Sub ThreadExceptionHandler2(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
        MsgBox("SecondHandler")
    End Sub
End Class
Denis
  • 11,796
  • 16
  • 88
  • 150
  • That does sound odd. Which one do you get? – Joe White Oct 24 '11 at 19:58
  • 2
    By design. The event has a custom add accessor. Which doesn't add the handler to a delegate, it replaces it. There can only be one handler, last one wins. – Hans Passant Oct 24 '11 at 20:03
  • 2
    @HansPassant It doesn't look like this behavior is documented, so I'd hesitate to call it "by design". Can you cite a source that says it's supposed to be that way? – Joe White Oct 24 '11 at 20:10

1 Answers1

4

Huh. Apparently so.

According to dotPeek, here's the code for the add and remove handlers for Application.ThreadException:

public static event ThreadExceptionEventHandler ThreadException
{
  add
  {
    System.Windows.Forms.IntSecurity.AffectThreadBehavior.Demand();
    Application.ThreadContext threadContext =
      Application.ThreadContext.FromCurrent();
    lock (threadContext)
      threadContext.threadExceptionHandler = value;
  }
  remove
  {
    Application.ThreadContext threadContext =
      Application.ThreadContext.FromCurrent();
    lock (threadContext)
      threadContext.threadExceptionHandler -= value;
  }
}

Notice how, in the remove handler, it uses -= as expected, but in the add handler, it just uses =? You'd think that should be +=, but it looks like it is not.

So yes, when you use the += operator to add a new event handler (which translates to a call to the add handler), WinForms is actually replacing the existing handler instead of adding to it.

Looks like a bug, plain and simple. If you write this up on Connect, post a link here so others can vote for it.

Joe White
  • 94,807
  • 60
  • 220
  • 330
  • Feature, not a bug. Nothing good happens when more than one handler tries to report/handle the exception. – Hans Passant Oct 24 '11 at 20:15
  • ... particularly because [memory leaks could occur](http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception%28v=VS.100%29.aspx) with this is a static event(if not detached when application ends). – Tim Schmelter Oct 24 '11 at 20:22
  • 3
    @HansPassant, yes, multiple handlers *could* be trouble. But if MS intended to only allow one handler, an event is the worst way to do it -- a `SetHandler` method would be much clearer. Add in the facts that `remove` *does* use `-=`, and that this behavior is unexpected and undocumented, and it all smells much more like a bug than a feature. – Joe White Oct 24 '11 at 20:23
  • @HansPassant the real reason I can across this is because I was inheriting from a third-party product we purchased. I wanted to enhance their error handling and started capturing ThreadException. All of a sudden, their exception handling went kaput. So in this case I would have preferred they handle the exceptions and I can do additional exception handling – Denis Oct 24 '11 at 21:07
  • 4
    From the documentation of ThreadException: "Attach your event handlers to the ThreadException event to deal with these exceptions..." Note the "s" in event handlers. Also, if it was by design, I'd expect that an exeception would be thrown when trying to add a second handler. Looks like a bug to me. – Meta-Knight Oct 25 '11 at 02:30