Microsoft KB Archive/810228

= How to establish a COM event sink with return values in the .NET Framework by using Visual Basic .NET or Visual Basic 2005 =

Article ID: 810228

Article Last Modified on 12/3/2007

-

APPLIES TO


 * Microsoft .NET Framework 2.0
 * Microsoft .NET Framework 1.0
 * Microsoft Visual Basic 2005
 * Microsoft Visual Basic .NET 2003 Standard Edition
 * Microsoft Visual Basic .NET 2002 Standard Edition

-





For a Microsoft Visual C# .NET version of this article, see 811645.

This article refers to the following Microsoft .NET Framework Class Library namespace:
 * System.Runtime.InteropServices



IN THIS TASK
 * SUMMARY
 * MORE INFORMATION
 * Classic COM Connection Point Model
 * .NET Delegate Event Model
 * Problems in the .NET Delegate Event Model with Return Values
 * REFERENCES



SUMMARY
This step-by-step article describes how to declare and establish a COM event sink by using sink objects in Microsoft Visual Basic .NET or in Microsoft Visual Basic 2005. The sample that appears in this article creates one sink object that implements all the events that are exposed by the COM server. The COM server uses return values from multiple events for later computations.

This article also describes the problems that may occur when you use a delegate model where the COM server cannot use return values from multiple events.

back to the top



MORE INFORMATION
Note This article assumes that MySrv is a user-defined COM server that is registered and exists on the system. The COM server exposes two events, Initialize and CanShutdown. The COM server uses these events as follows:
 * 1) The COM server fires the Initialize event, and then stores the value in a variable.
 * 2) The COM server fires the CanShutDown event, and then stores the value in a variable.

&quot;Event source&quot; refers to the COM server and &quot;event sink&quot; refers to the Microsoft .NET client throughout this article. For more information, visit the following Microsoft Web site:

http://msdn2.microsoft.com/en-us/library/ms683835.aspx

Microsoft .NET client consumes COM events by using the following:
 * A classic COM connection point model.
 * A Microsoft .NET delegate event model.

back to the top

Classic COM Connection Point Model
You can connect to a COM server by using the COM connection point interfaces from managed code. All COM event classes provide the IConnectionPointContainer interface. When you have the IConnectionPointContainer interface, you must find the specific connection point of the event interface that you want to subscribe to.

To use the classic COM connection point model, follow these steps:  In Microsoft Visual Studio .NET or in Microsoft Visual Studio 2005, click File, and then click New Project. For Project Type, click Visual Basic. For Template, click Console Application. Name your project SampleClient, and then click OK. In Solution Explorer, right-click Reference, and then click Add Reference to create a reference to MyAtlSrv. Click the COM tab, and then click the MySrv COM object. Click OK.</li> In Solution Explorer, right-click SampleClient, and then click Add Class to create the class for handling events.</li> Type MyEventsSink.vb in the text box, click the Class template, and then click Open.</li>  To establish a COM event sink, use the following sample code to modify the existing MyEventsSink class: Imports MySrvLib Public Class MyEventsSink Implements _IMySrvEvents

Public Function CanShutdown as Boolean Implements _IMySrvEvents.CanShutdown Console.WriteLine(&quot;CanShutdown interface method&quot;) Return True End Sub

Public Function Initialize as Boolean Implements _IMySrvEvents.Initialize Console.WriteLine(&quot;Initialize interface method&quot;) Return True End Sub

End Class </li>  In the Main method of Module1.vb, use the FindConnectionPoint method to obtain the IConnectionPoint interface. To subscribe to the event, use the Advise method by using the following code: Imports MySrvLib Imports System.Runtime.InteropServices Module Module1 Sub Main Dim cookie As Integer Dim mySink As MyEventsSink = New MyEventsSink Dim myServerClass As MySrvClass = New MySrvClass Dim icpc As UCOMIConnectionPointContainer = CType(myServerClass, UCOMIConnectionPointContainer) Dim icp As UCOMIConnectionPoint Dim IID_IMyEvents As Guid = GetType(_IMySrvEvents).GUID icpc.FindConnectionPoint(IID_IMyEvents, icp) icp.Advise(mySink, cookie)

'Call to server function causes events to be raised. myServerClass.SetParameter icp.Unadvise(cookie) End Sub End Module </li></ol>

back to the top

Microsoft .NET Delegate Event Model
In the delegate event model, each time that an event handler is registered, a COM sink object is created. To use the delegate model for implementing the sink for MySrv server, you can implement two delegates. In the following pseudo code, two event handlers are registered. Therefore, two COM sink objects are created: Imports MySrvLib Public WithEvents mySvrc As New MySrvClass ... Public Function re_Initialize As Boolean Handles mySvrc.Initialize Console.WriteLine(&quot;Initialize delegate&quot;) Return True End Function

Public Function re_CanShutdown As Boolean Handles mySvrc.CanShutdown Console.WriteLine(&quot;CanShutdown delegate&quot;) Return True End Function Sub Main mySvrc.SetParameter End Sub ... This client pseudo code implements the two delegates as two complete IMyEvents sinks:
 * The first delegate sink implements the Initialize event by calling the re_Initialize delegate. The first event sink also provides default implementation for the CanShutdown event, and then returns false as a default value.
 * The second delegate sink implements the CanShutdown event by calling the re_CanShutdown delegate. The second event sink also provides default implementation for the Initialize event, and then returns false as a default value.

back to the top

Problems in the .NET Delegate Event Model with Return Values
The following problems occur:
 * The COM server fires the Initialize event for the first event sink, and then returns true from the re_Initialize delegate. Also, the COM server fires the CanShutdown event for the first event sink, and then always returns a default value of false. However, the expected behavior of the CanShutdown event is to return a value of true.
 * The COM server fires the Initialize event for the second event sink, and then always returns a default value of false. Also, the COM server fires the CanShutdown event for the second sink, and then returns true. However, the expected behavior of the Initialize event is to return a value of true.

These problems occur when you use the return values from events because the event source cannot distinguish between the default return value and the actual return value.

The delegate event model with COM event interfaces also introduces overheads. For example, if you have nine methods in an event interface:
 * 1) To handle all nine methods in the interface, you create nine delegates.
 * 2) These delegates generate nine event sinks.
 * 3) If the COM server fires one event method, the .NET Framework formulates nine calls to the default generated methods.

However:
 * 1) To handle three of the nine methods in the event interface, you create three delegates.
 * 2) These delegates generate three event sinks.
 * 3) If the COM server fires one event method, the .NET Framework formulates three calls to the default generated methods.

This behavior may not be acceptable.

To work around this behavior, create a .NET COM client by using the classic COM connection point model, as described in the &quot;More Information&quot; section of this article.

back to the top

<div class="references_section">