C# COM object not being released

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Willy Denoyette [MVP]

    #16
    Re: C# COM object not being released


    "techie" <techie@nospam. biz> wrote in message
    news:EeednZwu35 rNrCrfRVn-gA@biscit.net.. .[color=blue]
    > The main application is an MFC Windows application with a UI. The main
    > MFC
    > application creates a COM object. The COM object is a C# .NET COM object.
    > Therefore, my COM object is a STA thread? How do I get my COM object to
    > pump the message queue?
    >
    >[/color]

    Ok, its a MFC windows application creating a .NET COM object.
    1. You don't have to pump messages, like I said this is handled by the UI
    thread.
    2. You COM object will live in the same STA thread as the UI.
    3. COM objects are released when you call Release() on their inferfaces.
    4. The .NET object will be collected when the GC runs (for objects without
    destructors), or when the finalizer runs (for objects that have destructors
    but not implementing IDisposable). Note the the finalizer runs on a
    finalizable object after the second sweep of the GC. If this object is the
    sole .NET COM object in the process chances are that the GC never runs, so
    the finalizer will not run either, in that case the finalizer will run when
    the process shuts down.
    So I suggest you apply the Disposing pattern and remove the finalizer
    (destructor).

    Willy.


    Comment

    • techie

      #17
      Re: C# COM object not being released

      Can you please check my code for the Disposing pattern. I'm still getting a
      memory leak. Dispose nevers gets called. I've removed the destructor
      (~Import).

      [ClassInterface( ClassInterfaceT ype.None)]
      [ProgId("SI.Impo rt")]
      public class Import :IImportFilter, IDisposable
      {
      Session m_Session;
      Content m_Content;
      bool disposed = false;
      ..
      ..
      public void Dispose()
      {
      Dispose(true);
      }

      protected virtual void Dispose(bool disposing)
      {
      if (!disposed)
      {
      if (disposing)
      {
      ComHelper.SafeR eleaseComObject (m_Content);
      ComHelper.SafeR eleaseComObject (m_Session);
      }
      disposed = true;
      }
      }

      }

      There are two unmanaged COM objects that need to be destroyed.
      ..

      "Willy Denoyette [MVP]" <willy.denoyett e@telenet.be> wrote in message
      news:OJbmZdedFH A.3620@TK2MSFTN GP09.phx.gbl...[color=blue]
      >
      > "techie" <techie@nospam. biz> wrote in message
      > news:EeednZwu35 rNrCrfRVn-gA@biscit.net.. .[color=green]
      > > The main application is an MFC Windows application with a UI. The main
      > > MFC
      > > application creates a COM object. The COM object is a C# .NET COM[/color][/color]
      object.[color=blue][color=green]
      > > Therefore, my COM object is a STA thread? How do I get my COM object to
      > > pump the message queue?
      > >
      > >[/color]
      >
      > Ok, its a MFC windows application creating a .NET COM object.
      > 1. You don't have to pump messages, like I said this is handled by the UI
      > thread.
      > 2. You COM object will live in the same STA thread as the UI.
      > 3. COM objects are released when you call Release() on their inferfaces.
      > 4. The .NET object will be collected when the GC runs (for objects without
      > destructors), or when the finalizer runs (for objects that have[/color]
      destructors[color=blue]
      > but not implementing IDisposable). Note the the finalizer runs on a
      > finalizable object after the second sweep of the GC. If this object is the
      > sole .NET COM object in the process chances are that the GC never runs, so
      > the finalizer will not run either, in that case the finalizer will run[/color]
      when[color=blue]
      > the process shuts down.
      > So I suggest you apply the Disposing pattern and remove the finalizer
      > (destructor).
      >
      > Willy.
      >
      >[/color]


      Comment

      • Willy Denoyette [MVP]

        #18
        Re: C# COM object not being released


        The CCW will not call Dispose() automatically when it's ref. count reaches
        0, your client has to call Dispose() explicitly just like any other managed
        client should do, I guess you don't call Dispose() from the client.
        Also note that calling Dispose won't free the "Import" 'managed COM'
        object, this is done at the next GC run (non-deterministical ly), I hope this
        is not the 'memory leak' your are referring to - this is not a memory leak
        but the normal behavior.
        I also suppose that SafeReleaseComO bject is used to eagerly release other
        unmanaged resources, if not you shouldn't implement IDisposable at all.

        Willy.

        "techie" <techie@nospam. biz> wrote in message
        news:i7ydnaea39 IrAirfRVn-1A@biscit.net.. .[color=blue]
        > Can you please check my code for the Disposing pattern. I'm still getting
        > a
        > memory leak. Dispose nevers gets called. I've removed the destructor
        > (~Import).
        >
        > [ClassInterface( ClassInterfaceT ype.None)]
        > [ProgId("SI.Impo rt")]
        > public class Import :IImportFilter, IDisposable
        > {
        > Session m_Session;
        > Content m_Content;
        > bool disposed = false;
        > ..
        > ..
        > public void Dispose()
        > {
        > Dispose(true);
        > }
        >
        > protected virtual void Dispose(bool disposing)
        > {
        > if (!disposed)
        > {
        > if (disposing)
        > {
        > ComHelper.SafeR eleaseComObject (m_Content);
        > ComHelper.SafeR eleaseComObject (m_Session);
        > }
        > disposed = true;
        > }
        > }
        >
        > }
        >
        > There are two unmanaged COM objects that need to be destroyed.
        > .
        >
        > "Willy Denoyette [MVP]" <willy.denoyett e@telenet.be> wrote in message
        > news:OJbmZdedFH A.3620@TK2MSFTN GP09.phx.gbl...[color=green]
        >>
        >> "techie" <techie@nospam. biz> wrote in message
        >> news:EeednZwu35 rNrCrfRVn-gA@biscit.net.. .[color=darkred]
        >> > The main application is an MFC Windows application with a UI. The main
        >> > MFC
        >> > application creates a COM object. The COM object is a C# .NET COM[/color][/color]
        > object.[color=green][color=darkred]
        >> > Therefore, my COM object is a STA thread? How do I get my COM object
        >> > to
        >> > pump the message queue?
        >> >
        >> >[/color]
        >>
        >> Ok, its a MFC windows application creating a .NET COM object.
        >> 1. You don't have to pump messages, like I said this is handled by the UI
        >> thread.
        >> 2. You COM object will live in the same STA thread as the UI.
        >> 3. COM objects are released when you call Release() on their inferfaces.
        >> 4. The .NET object will be collected when the GC runs (for objects
        >> without
        >> destructors), or when the finalizer runs (for objects that have[/color]
        > destructors[color=green]
        >> but not implementing IDisposable). Note the the finalizer runs on a
        >> finalizable object after the second sweep of the GC. If this object is
        >> the
        >> sole .NET COM object in the process chances are that the GC never runs,
        >> so
        >> the finalizer will not run either, in that case the finalizer will run[/color]
        > when[color=green]
        >> the process shuts down.
        >> So I suggest you apply the Disposing pattern and remove the finalizer
        >> (destructor).
        >>
        >> Willy.
        >>
        >>[/color]
        >
        >[/color]


        Comment

        • techie

          #19
          Re: C# COM object not being released

          OK, I will call Dispose() from my MFC client. Thanks for your help so far.
          Is actually possible to QueryInterface for IDisposable?

          If I have an ASP.NET application, instead of my MFC client, that creates a
          C++ COM object which in turn creates my C# COM object do I have to implement
          the IDisposable interface? Isn't this necessary for the GC to destroy all
          unreferenced objects? Or do I just call Dispose() explicitly like in the
          MFC client?


          "Willy Denoyette [MVP]" <willy.denoyett e@telenet.be> wrote in message
          news:Oy78EJldFH A.412@tk2msftng p13.phx.gbl...[color=blue]
          >
          > The CCW will not call Dispose() automatically when it's ref. count reaches
          > 0, your client has to call Dispose() explicitly just like any other[/color]
          managed[color=blue]
          > client should do, I guess you don't call Dispose() from the client.
          > Also note that calling Dispose won't free the "Import" 'managed COM'
          > object, this is done at the next GC run (non-deterministical ly), I hope[/color]
          this[color=blue]
          > is not the 'memory leak' your are referring to - this is not a memory leak
          > but the normal behavior.
          > I also suppose that SafeReleaseComO bject is used to eagerly release other
          > unmanaged resources, if not you shouldn't implement IDisposable at all.
          >
          > Willy.[/color]



          Comment

          Working...