locked
Release C # object that is COM interop RRS feed

  • Question

  • I created a C# class with interface and selected the Register for COM interop.  I was able to create an instance of this class and call its methods and properties from a C++ application.  However, I noticed that if the oject is released and then attempt to create an instance of the class again, it fails with the HRESULT = 0x80070020 (The process cannot access the file because it is being used by another process. )  When I exit the program and restart it, it works for the first attempt to create an instance.  Is there a way to release the object such that it can be instantiated again and how is it accomplished.

    I also noticed that if I create an instance of the class using new from a C# application, it behaves the same way; however, if I can create multiple instances of other classes that comprise the dll.

    Friday, March 18, 2011 4:23 PM

Answers

  • Hello Masoneilan,

     

    1. >> However, I noticed that if the oject is released and then attempt to create an instance of the class again, it fails with the HRESULT = 0x80070020 (The process cannot access the file because it is being used by another process. )... I also noticed that if I create an instance of the class using new from a C# application, it behaves the same way...

    1.1 From the description of the problem, it does not look like a COM interop problem. It looks more like an internal implementation issue of your C# class.

     

    2. >> Is there a way to release the object such that it can be instantiated again and how is it accomplished...

    2.1 There should be no problem instantiating as many COM classes as required, whether each instance is released or not.

    2.2 There is no special technique for a COM client to use to release and then re-instantiate a COM class whether the COM class is implemented in managed code or otherwise.

    2.3 However, note the points mentioned in the next section.

     

    3. Concerning the Release of COM Objects implemented in Managed Code.

    3.1 When the reference count of a COM-Callable Wrapper for a .NET object reaches zero, the .NET object becomes merely eligible for garbage collection. It's actual time of destruction remains non-deterministic.

    3.2 One design technique to ensure timely release of critical resources (when an object is no longer required) is to implement the IDisposable interface for the .NET object and then get the client code to call the Dispose() method. Critical resources can then be released in the Dispose() method instead of being release in the C# class' Finalize method (i.e. the destructor).

     

    4. Suggestion

    4.1 I suggest that you start investigating the problem by creating a new C# class that implements the same interface mentioned in the OP. However, for this class, provide only trivial implementation code for the methods of the class.

    4.2 Make sure that it can be instantiated, released and reinstantiated by a C++ client. Also make sure that it can be instantiated multiple times by a C# client.

    4.3 Then slowly and incrementally add functionality to the C# class. Perform thorough instantiation tests after each incremental change.

    4.4 You should be able to detect the source of the bottleneck this way.

     

    Best of luck, Masoneilan,

    - Bio.

     


    • Proposed as answer by Aspen VJ Monday, March 21, 2011 7:05 AM
    • Marked as answer by Larcolais Gong Wednesday, March 30, 2011 2:23 PM
    Saturday, March 19, 2011 3:34 AM

All replies

  • Hello Masoneilan,

     

    1. >> However, I noticed that if the oject is released and then attempt to create an instance of the class again, it fails with the HRESULT = 0x80070020 (The process cannot access the file because it is being used by another process. )... I also noticed that if I create an instance of the class using new from a C# application, it behaves the same way...

    1.1 From the description of the problem, it does not look like a COM interop problem. It looks more like an internal implementation issue of your C# class.

     

    2. >> Is there a way to release the object such that it can be instantiated again and how is it accomplished...

    2.1 There should be no problem instantiating as many COM classes as required, whether each instance is released or not.

    2.2 There is no special technique for a COM client to use to release and then re-instantiate a COM class whether the COM class is implemented in managed code or otherwise.

    2.3 However, note the points mentioned in the next section.

     

    3. Concerning the Release of COM Objects implemented in Managed Code.

    3.1 When the reference count of a COM-Callable Wrapper for a .NET object reaches zero, the .NET object becomes merely eligible for garbage collection. It's actual time of destruction remains non-deterministic.

    3.2 One design technique to ensure timely release of critical resources (when an object is no longer required) is to implement the IDisposable interface for the .NET object and then get the client code to call the Dispose() method. Critical resources can then be released in the Dispose() method instead of being release in the C# class' Finalize method (i.e. the destructor).

     

    4. Suggestion

    4.1 I suggest that you start investigating the problem by creating a new C# class that implements the same interface mentioned in the OP. However, for this class, provide only trivial implementation code for the methods of the class.

    4.2 Make sure that it can be instantiated, released and reinstantiated by a C++ client. Also make sure that it can be instantiated multiple times by a C# client.

    4.3 Then slowly and incrementally add functionality to the C# class. Perform thorough instantiation tests after each incremental change.

    4.4 You should be able to detect the source of the bottleneck this way.

     

    Best of luck, Masoneilan,

    - Bio.

     


    • Proposed as answer by Aspen VJ Monday, March 21, 2011 7:05 AM
    • Marked as answer by Larcolais Gong Wednesday, March 30, 2011 2:23 PM
    Saturday, March 19, 2011 3:34 AM
  • Try:

    For each COM object call: 

    while (System.Runtime.InteropServices.Marshal.ReleaseComObject(comObject) > 0){}

    And after call:

    GC.Collect();
    GC.WaitForPendingFinalizers();
    

    Saturday, March 19, 2011 6:22 PM
  • Hi Masoneilan,

    Any update? Has your question been resolved?

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 28, 2011 1:55 AM