CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

Handles versus Addhandler , a crash course in VB.NET event support (Error 459 revisited)

In my previous post on the handling of COM events I described how I was driven into the arms of VB.NET. A VB.NET class published to COM sinks events as desired, a C# class pops up a mysterious error 459. With the help of feedback I've been delving a little deeper into this.

Events are handled by event handling methods. The way to set these in C# is by adding a delegate object to the event :

       FileSystemWatcher watcher = new FileSystemWatcher(dirName, filter);
       watcher.Created += new FileSystemEventHandler(watcher_Created);

...

       private void watcher_Created(object sender, FileSystemEventArgs e)
       {
           // Do something
       }
 

The usual way to set event handlers in VB is by using the handles keyword :

    Private WithEvents fw As New FileSystemWatcher
 

    Private Sub watcher_Created(ByVal sender As Object, ByVal e As FileSystemEventArgs) Handles fw.Created
        'Do something
    End Sub
 

The nice way about the C# syntax is that it's no problem to hook in multiple methods as event handler's to the same event:

    watcher.Created += new FileSystemEventHandler(watcher_Created);
    watcher.Created += new FileSystemEventHandler(anotherwatcher);
 

You can do the same thing, in VB.NET. In my post I admitted not knowing how to do that, Sean pointed me to the syntax to get that done using the AddHandler keyword. Instead of using handles the code could be written  as

Public Class Class1
    Private WithEvents fw As New FileSystemWatcher
    Private Sub watcher_Created(ByVal sender As Object, ByVal e As FileSystemEventArgs)
        'Do something
    End Sub

    Public Sub New()
        AddHandler fw.Created, AddressOf watcher_Created
    End Sub

End Class
 

Using this syntax I found out my VB.NET COM class started popping up the same 459 errors as the C# class. Apparently I was on to something.

Inspecting the actual code using Reflector shows that Handles and AddHandler have a subtle difference in the generated code.

The disassembly of a class using handles

constructor .ctor()

Public Sub New()
Me.fw = New FileSystemWatcher End Sub

Property setter of the object whose events are handled

<MethodImpl(MethodImplOptions.Synchronized)> _
Private Overridable Sub set_fw(ByVal WithEventsValue As FileSystemWatcher)
If (Not Me._fw Is Nothing) Then RemoveHandler Me._fw.Created, New FileSystemEventHandler(AddressOf Me.watcher_Created)
End If Me._fw = WithEventsValue If (Not Me._fw Is Nothing) Then AddHandler Me._fw.Created, New FileSystemEventHandler(AddressOf Me.watcher_Created)
End If End Sub

The disassmbly of the class when it sets the event handler in the constructor

Constructor .ctor

Public Sub New()
Me.fw = New FileSystemWatcher AddHandler Me.fw.Created, New FileSystemEventHandler(AddressOf Me.watcher_Created)
End Sub

Fw property setter

<MethodImpl(MethodImplOptions.Synchronized)> _
Private Overridable Sub set_fw(ByVal WithEventsValue As FileSystemWatcher)
If (Not Me._fw Is Nothing) Then End If Me._fw = WithEventsValue If (Not Me._fw Is Nothing) Then End If End Sub

The handles keyword does translates to an AddHandler statement. But instead of in the constructor this statement is in the property setter of the object whose event is handled and adds the delegate to the internal object instead of its property wrapper. Apparently this subtle difference is enough to provide COM with a good event support. It matches the somewhat cryptic description Although you might think you could sink the events from the implemented object, that isn't automatically the case  on msdn.

The difference between C# and VB.NET is not the language itself but the code generation, I would not know of a way to alter that.


Published Aug 02 2005, 07:56 PM by pvanooijen
Filed under:

Comments

Daniel Moth said:

> Sean pointed me to the syntax to get that done using the AddHandler keyword

Haven't read the whole article but on the specific point on multiple handlers for a sinlge event.... in addition to the AddHandler/AddressOf approach, you can append to Handles using commas other <object>.<event> pairs.
# August 2, 2005 6:39 PM

chid said:

Also, when you use Addhandler instead of handles, you can omit the "WithEvents" keyword.

-Mike
# August 2, 2005 9:41 PM

pvanooijen said:

Daniel,

A handles statement containing multiple pairs is a nice extra. Missed that. But it's not dynamic, you cannot add handlers on the fly.

Mike,

OK. Point taken. But it doesn't make a difference for the generated code.

I never realized VB is a such complicated language :)
# August 3, 2005 4:20 AM

Peter's Gekko said:

&#196;fter a crash course comes sinking in. This post is a rewrite of yesterdays one on events in VB.NET....
# August 3, 2005 4:37 PM

Peter's Gekko said:

After a crash course comes sinking in. This post is a rewrite of yesterdays one
on events in VB.NET....
# August 4, 2005 4:23 AM

Peter's Gekko said:

After a crash course comes sinking in. This post is a rewrite of yesterdays one
on events in VB.NET....
# August 5, 2005 12:07 PM

Peter's Gekko said:

Recently I had trouble getting COM events to work in a COM automation server written in C#. A visitor's...
# August 31, 2005 4:08 PM

Peter's Gekko said:

At first sight creating COM clients and servers with .NET looks like a snap. As I recently found out...
# August 31, 2005 4:08 PM

Peter's Gekko said:

Recently I had trouble getting COM events to work in a COM automation server written in C#. A visitor's...
# August 31, 2005 4:11 PM

Peter's Gekko said:

At first sight creating COM clients and servers with .NET looks like a snap. As I recently found out...
# August 31, 2005 4:12 PM

Peter's Gekko said:

Recently I had trouble getting COM events to work in a COM automation server written in C#. A visitor's...
# September 1, 2005 11:54 AM

Joey said:

One other item I've had occur when I least expect it is losing the Handles on some methods (or all on a particular .vb class). It appears to be an undocumented feature in VS.NET. This behavior has never occurred using the AddHandler method.
# September 15, 2005 2:23 PM

pvanooijen said:

Several designers in VS have the habit of "losing" an assigned handler. My biggest frustration is the web form designer.
Supposed to be better in 2005. Hasn't happened there yest...
# February 6, 2006 3:36 AM

Kent Lee said:

I am using shared events and use the addHandler syntax to add the event handler for the event. However, every once in a while the events seem to get lost and my event handler doesn't see them. This doesn't happen often, but often enough to be very annoying.

Have you heard of this happening? It happened with .NET 1.1 and now happens with .NET 2.0

I'm writing in VB.NET for both .NET frameworks.

# May 24, 2007 10:10 PM

pvanooijen said:

In 1.1. it used to be a habit of VS 2003. I wouldn't be surprised VS 2005 showing this same feature once in a while as well :/

# June 5, 2007 3:02 AM

Leeor said:

You will find that in some instances you will need to explicitly register dynamically rendered handlers.  

Example:

AddHandler MySaveNowButton.Click, AddressOf MySaveNowEventHandler

MyPage.RegisterRequiresRaiseEvent(MySaveNowButton)

# November 8, 2007 3:31 PM

Dominique said:

Hello,

If I add "Handles buttonHourUp, buttonMinuteUp" to my routine it fails...

Private Sub buttonUp_Click(ByVal sender As Object, ByVal e As System.EventArgs)

   If m_currentNumber = MaxValue Then

       m_currentNumber = MinValue

       m_currentTotal = 0

   Else

       m_currentNumber += 1

       m_currentTotal = m_currentNumber

   End If

   DisplayNumber()

End Sub

why?

# December 10, 2007 7:04 PM

pvanooijen said:

Please be more precise

# December 11, 2007 3:55 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!