none
Can I have CCW call Dispose on COM Exposed .NET Class when COM Ref Count Reaches Zero? RRS feed

  • Question

  • Good morning,

    Is there a way for a VB.NET COM exposed component to be notified by the CCW when its COM reference count has reached zero and to call its Dispose() method?  Or can you get the CCW to call Dispose() when the COM reference count reaches zero?

    I've recently upgraded a VB6 component to VB.NET and am having some resource cleanup issues.  The VB.NET component is exposed to COM and creates a COM+ reference which it keeps open for the lifetime of the object.  The VB.NET component is used by a VB6 client which basically does a:

    VB6:

    Dim objProxy As New clsVBNet
    objProxy.SomeMethod
    Set objProxy = Nothing

    My VB.NET component still holds open its reference to its COM+ object until it is collected by the GC.
    The VB6 component that was upgraded rewritten as the VB.NET component did the same thing, but when doing a Set objProxy = Nothing in VB6, the VB6 component that was hold the COM+ object was immediately cleaned up.

    I've added a Finalizer to my VB.NET component so everything cleans up fine, but I don't want to have to wait or rely on the GC to cleanup my resources for me.  I can modify my VB6 client to explicitly call Dispose() for me:

    VB6:

    Dim objProxy As New clsVBNet
    objProxy.SomeMethod
    Call objProxy.Dispose
    Set objProxy = Nothing

    But I'd prefer not to have to since this will require changing heaps of VB6 code.

    The other option I thought of was to use a timer on the VB.NET component to cleanup when it detects that it isn't being used by COM anymore:

    Private Sub mTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles mTimer.Elapsed
       Dim refToMe As IntPtr = Marshal.GetIUnknownForObject(Me)
       Dim refCount As Integer = Marshal.Release(refToMe)
       If refCount = 0 Then
          ' Release COM+ reference
          Me.Dispose()
       End If
    End Sub

    So basically, my two known options at the moment are:
    1) Change every Set obj = Nothing in VB6 code to include a call to Dispose() beforehand
    2) Change my VB6 upgraded VB.NET component to include a timer that waits until it detects that there are no COM references to it.

    The first option is cleaner but will require heaps more work for me.

    So, is there a way for my VB.NET COM exposed component to be notified by the CCW that is exposing it to COM when its reference count has reached zero and I can cleanup synchronously?

    Thanks in advance!
    Jason.

    Thursday, March 11, 2010 12:23 AM

Answers

  • I don't know why you're worrying about this. If you want Win32 behavior then don't use managed code, and trying to get some managed code to work like Win32 code seems pointless to me.  As far as I'm concerned your best option is to do nothing at all about this.

    Dispose has got nothing to do with this. That is for releasing unmanaged resources, so it's not clear to me why Dispose is relevant in this case.

    As for a solution anyway, it's possible that calling CoFreeUnusedLibraries from your VB6 code might have the effect you want. However keep in mind that there might be counted references you can't see because of the unmanaged code<=>managed code mechanism through the CCW. It might have references of its own that it keeps alive.


    Phil Wilson
    • Marked as answer by jhess001 Sunday, March 14, 2010 11:50 PM
    Thursday, March 11, 2010 9:40 PM

All replies

  • I don't know why you're worrying about this. If you want Win32 behavior then don't use managed code, and trying to get some managed code to work like Win32 code seems pointless to me.  As far as I'm concerned your best option is to do nothing at all about this.

    Dispose has got nothing to do with this. That is for releasing unmanaged resources, so it's not clear to me why Dispose is relevant in this case.

    As for a solution anyway, it's possible that calling CoFreeUnusedLibraries from your VB6 code might have the effect you want. However keep in mind that there might be counted references you can't see because of the unmanaged code<=>managed code mechanism through the CCW. It might have references of its own that it keeps alive.


    Phil Wilson
    • Marked as answer by jhess001 Sunday, March 14, 2010 11:50 PM
    Thursday, March 11, 2010 9:40 PM
  • Thanks for your help.  The VB.NET COM exposed component contains an unmanaged resource which is were Dispose comes in.  It's too bad that the CCW doesn't have an option for raising an event or something when it has finished with the managed instance of my class.

    Thanks!
    Jason.

    Sunday, March 14, 2010 11:49 PM