Unsubscribing to events from COM Client doesn't work  
Author Message
Fredrik Pålsson





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

I've created a .Net component that has a COM interface. This interface contains events.

I've also got a VB6 client that connects to this component. It recieves the events using the VB6 WithEvents "mechanism".

Setting the WithEvents variable in VB6 to nothing doesn't make the events stop fireing.

Looking deeper into the problem I see that the IConnectionPoint->UnAdvise call that the VB6 client makes when setting the WithEvents variable to nothing fails with error code 0x80040200. The problem gets worse if I set the WithEvents variable to a different object, since the first object still fires events, even if I have no reference to it anymore.

I get the same result using VB.Net as C# to create the component.

Is this a bug in the CCW/Interop stuff

Source below:

VB.NET

<Microsoft.VisualBasic.ComClass()> Public Class DET

Private _t As System.Threading.Timer = Nothing

Public Event TestEvent(ByVal Info As String)

Public Sub New()

_t = New System.Threading.Timer(AddressOf tcb)

_t.Change(5000, 5000)

End Sub

<System.Runtime.InteropServices.ComVisible(False)> Private Sub tcb(ByVal sender As Object)

RaiseEvent TestEvent("Timer " + DateTime.Now.ToString())

End Sub

Public Sub TestMet(ByVal Info As String)

RaiseEvent TestEvent(Info)

End Sub

End Class

C#

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

namespace DisconnectEventTest

{

public delegate void TestEventEventHandler(string Info);

[ComVisible(true)]

[Guid(DET.InterfaceId)]

public interface IDET

{

void TestMet(string Info);

}

[ComVisible(true)]

[Guid(DET.EventsId)]

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

public interface IDETEvents

{

void TestEvent(string Info);

}

[Guid(DET.ClassId)]

[ClassInterface(ClassInterfaceType.None)]

[ComSourceInterfaces(typeof(IDETEvents))]

[ComVisible(true)]

public class DET : MarshalByRefObject, IDET

{

internal const string ClassId = "11232094-ABC8-40dc-A9E5-70D87103E8D1";

internal const string InterfaceId = "12345452-28C1-429f-8CEA-86DF341E07B5";

internal const string EventsId = "7227632D-83DC-473e-8DA6-03FE71E62249";

public event TestEventEventHandler TestEvent;

private System.Threading.Timer _t = null;

public DET ()

{

_t = new System.Threading.Timer(tcb);

_t.Change(5000,5000);

}

private void tcb(object sender)

{

TestEvent.Invoke("Timer " + DateTime.Now.ToString());

}

public override object InitializeLifetimeService()

{ return null; }

public void TestMet(string Info)

{

TestEvent.Invoke (Info);

}

}

}

VB6 Client

Option Explicit

Private WithEvents m_DET As DisconnectEventTest.DET

Private Sub Command4_Click()
Set m_DET = New DisconnectEventTest.DET
End Sub

Private Sub Command1_Click()
m_DET.TestMet Now
End Sub

Private Sub Command2_Click()
Set m_DET = m_DET '<- Makes event fire multiple times, one for each execution (if m_DET isn't nothing, of cause)
End Sub

Private Sub Command3_Click()
Set m_DET = Nothing ' <- Doesn't make events stop fireing
End Sub

Private Sub m_DET_TestEvent(ByVal Info As String)
MsgBox Info
End Sub




.NET Development4  
 
 
nobugz





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

I'm not sure it is related but you are definitely breaking a COM rule. The event gets fired on a thread from the thread pool, not the thread that created the COM object. Especially VB6 has problems with that, it has very poor multi-threading support.


 
 
Fredrik Palsson





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

I'm aware of the thread problem mentioned, but I was trying to publish a simple test application. I'm quite sure this has nothing to do with the problem. Even if no event is triggered, you can see the invokationlist of the TestEvent event growing every time the client does Set m_DET = m_DET, and it doesn't get decrese when Set m_DET = Nothing is executed by the client.

Is there anyone who has the possibility to check what is acually going on here

Regards,

/ Fredrik



 
 
nobugz





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

Clearly, your problem is caused by the failing Unadvise call, the advise sink doesn't get disconnected. If you know how to trap Unadvise, look at the arguments to the Advise and Unadvise calls. If the cookies don't match, the problem is caused by VB6. If they do match, the problem is caused by the .NET wrapper.


 
 
Fredrik Palsson





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

Can you recommend a tool to hook the calls to Advise and Unadvise to enable me to examine the cookie parameter

 
 
nobugz





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

No, I was hoping you had one. How did you know that UnAdvise failed with HRESULT 0x80040200 It is the correct failure code...


 
 
Fredrik Palsson





PostPosted: Common Language Runtime, Unsubscribing to events from COM Client doesn't work Top

I used ComTrace (http://www.blunck.se/comtrace/comtrace.html), but that doesn't tell me the value of the parameters for Advise (just pointer address, not value of dword beeing pointed to).