none
VSTO and Office objects disposing RRS feed

  • Question

  • In the times of COM Interop it was strongly advised to keep an eye on Office objects, always clean it up after yourself by explicitly assigning null to them and even calling Marshal.ReleaseComObject sometimes.

    Has it changed in VSTO?
    I have an Outlook add-in written using COM Interop which I intend to move to VSTO. Each time an Outlook Object is used (items, folders, application, etc), there is either an explicit setting to null code or a dispose pattern. My question is whether it will be relevant under VSTO? Seems to me I can relax and remove all this manual cleanup, because the runtime should take care of it.
    Monday, August 4, 2008 10:14 AM

Answers

  • Hi Esalamatov,

     

    Sadly to say, VSTO runtime does not help us to dispose COM objects. It still depends on programmer to write codes performing cleaning up manually. The story goes as it did in COM Add-In times.

     

    The first approach is calling Marshal.ReleaseComObject() function by passing the COM Interop object as parameter. What to pay attention is we need to get all intermediary COM objects' handle, and call Marshal.ReleaseComObject() for all of them explicitly. See: http://blogs.msdn.com/geoffda/archive/2007/09/07/the-designer-process-that-would-not-terminate-part-2.aspx

     

    The second approach is disposing pattern. After no need to use the COM object any more, we can set them to null and call:

    GC.Collect();

    GC.WaitForPendingFinalizers();

    // Only call if you care about reclaiming RCW memory right now.

    GC.Collect();

    Please refer the following Geoff's article on this aspect.

    http://blogs.msdn.com/geoffda/archive/2007/08/31/the-designer-process-that-would-not-terminate.aspx

     

     

     

    Thanks,

    Ji

    Wednesday, August 6, 2008 3:05 AM
    Moderator
  •  esalamatov wrote:
    In the times of COM Interop it was strongly advised to keep an eye on Office objects, always clean it up after yourself by explicitly assigning null to them and even calling Marshal.ReleaseComObject sometimes.

    Has it changed in VSTO?
    I have an Outlook add-in written using COM Interop which I intend to move to VSTO. Each time an Outlook Object is used (items, folders, application, etc), there is either an explicit setting to null code or a dispose pattern. My question is whether it will be relevant under VSTO? Seems to me I can relax and remove all this manual cleanup, because the runtime should take care of it.

    I started to answer this question yesterday, basically the same way Ji did. Then I opened the Carter & Lippert book and read that, in the case of OUTLOOK, there are major differences in how VSTO 2005 and VSTO 2008 Com Add-ins work compared to other types of COM Add-ins for Outlook. So since I'm a below-average end-user of Outlook, with no idea beyond that, I thought it better to leave it for a specialist. But at this point, I'm bringing it what I know...

     

    The answer really depends on what you're talking about in your question.

     

    Speaking of Outlook COM Add-ins pre-VSTO 2005 vs VSTO Add-ins, I'm going to type out some text from page 944 of "Visual Studio Tools for Office". Note that I have no experience with this, I'm just quoting and hope this answers your question. It appears no experienced Outlook folks are around this week (Sue Mosher, for example). If you want to discuss this in more detail I recommend visiting some of the newsgroup links listed in the Please Read First message, where you'll find many more Outlook specialists.

     

    "Outlook COM  add-in development requires you to track any variables set to Outlook objects, sind the Close events of the Inspector and Explorerer objects, set your vairables set to Outllok object to null when the last Inspector or Explorer closes or the Application object's Quit event is raised, and force two garbage collections. This complexity is not required when building add-ins for other Office applications, so do nto apply these techniques to Excel or Word. Excle and Word are more robust to reference counts on their COM objects being held during the shutting down of the applications. This situation also never occurs in VSTO 2005 customizations because of VSTO's better model for loading and unloading code.

     

    If you use the VSTO Outlook add-in project, you will not have to worry about any of these Outlook-specific shutdown problems or any of the problems that we said requried a *** in Chapter 23. The VSTO Outlook add-in project uses the VSTO mdoel for loading and unloading an add-in. The VSTO model alsways loads a customization into its own application domain. When the add-in is unloaded or the application exits, VSTO raises a Shutdown even tinto the customization. The developer does not have to set any objects to null or force a garbage collection to clean up RCWs because once the Shutdown event handler has been run, VSTO unloads the application domain associated with the customization..."

    Wednesday, August 6, 2008 9:24 AM
    Moderator
  • Hi,

     

    If you are just asking about cleanup at shutdown, then yes, the VSTO Runtime will generally take care of you.  We use AppDomain isolation for all types of customizations, so when the AppDomain is torn down, cleanup will occur,  One of the consequences of tearing down an AppDomain is that the Common Language Runtime (CLR) will execute finalization on *all* finalizable objects in the doomed AppDomain (regardless of whether they are rooted).  This means that all Runtime Callable Wrappers (RCWs) will be forced to release their COM references when the AppDomain unloads.  It is possible (however rare), that the finalizer thread can get blocked indefinitely.  If that happens, the CLR will have to abort finalization and any RCWs that have yet to be finalized will orphan their COM objects.  As I said, this would be extremely rare (likely due to a bug in a component's finalization code), so you may not find it worth considering.

     

    However, you may still be forced to think about explicit lifetime management of your COM objects for performance reasons.  The fundamental problem is that RCWs are relatively small objects, while the COM objects that they manage may be large.  Depending on what your Add-in does, you may not be able to wait for the generation 0 GC heap to fill up (which would force finalization on eligible RCWs, triggering the IUnknown::Release call).  IOW, your add-in might be creating COM objects at an undesirable rate, creating unnecessary memory pressure and hurting performance.  In that situation, you will need to choose a strategy to explicitly release your COM objects.

     

    My recommendation would be to run perfmon and watch what happens to process private bytes while your add-in is running under various usage cases.  Private bytes represent the total amount of memory that the process has allocated.  The question will be to what extent private bytes grow (and the impact on performance) before they shrink again when the generation 0 heap finally fills and the system automatically performs a GC.  What you are trying to avoid is a situation where your add-in consumes so much physical memory that you start triggering hard page-faults.  If memory usage gets large, start looking at process page faults per second, as well as what is happening with the physical hard disk. If page faults and reads start jumping, then you know you have a performance problem which you will want to address by engaging in an explicit release strategy to limit the amount of memory that your add-in consumes.

     

    In terms of explicit release strategies, they are pretty well summed up in the blog entries that Ji mentions.  However, I do want to point out that setting an object to null simply makes it eligible for GC; it does not result in any memory being freed or any finalizers being run.

     

    Sincerely,

     

    Geoff Darst

    Microsoft VSTO Team

     

    Wednesday, August 6, 2008 3:53 PM
    Answerer

All replies

  • Hi Esalamatov,

     

    Sadly to say, VSTO runtime does not help us to dispose COM objects. It still depends on programmer to write codes performing cleaning up manually. The story goes as it did in COM Add-In times.

     

    The first approach is calling Marshal.ReleaseComObject() function by passing the COM Interop object as parameter. What to pay attention is we need to get all intermediary COM objects' handle, and call Marshal.ReleaseComObject() for all of them explicitly. See: http://blogs.msdn.com/geoffda/archive/2007/09/07/the-designer-process-that-would-not-terminate-part-2.aspx

     

    The second approach is disposing pattern. After no need to use the COM object any more, we can set them to null and call:

    GC.Collect();

    GC.WaitForPendingFinalizers();

    // Only call if you care about reclaiming RCW memory right now.

    GC.Collect();

    Please refer the following Geoff's article on this aspect.

    http://blogs.msdn.com/geoffda/archive/2007/08/31/the-designer-process-that-would-not-terminate.aspx

     

     

     

    Thanks,

    Ji

    Wednesday, August 6, 2008 3:05 AM
    Moderator
  •  esalamatov wrote:
    In the times of COM Interop it was strongly advised to keep an eye on Office objects, always clean it up after yourself by explicitly assigning null to them and even calling Marshal.ReleaseComObject sometimes.

    Has it changed in VSTO?
    I have an Outlook add-in written using COM Interop which I intend to move to VSTO. Each time an Outlook Object is used (items, folders, application, etc), there is either an explicit setting to null code or a dispose pattern. My question is whether it will be relevant under VSTO? Seems to me I can relax and remove all this manual cleanup, because the runtime should take care of it.

    I started to answer this question yesterday, basically the same way Ji did. Then I opened the Carter & Lippert book and read that, in the case of OUTLOOK, there are major differences in how VSTO 2005 and VSTO 2008 Com Add-ins work compared to other types of COM Add-ins for Outlook. So since I'm a below-average end-user of Outlook, with no idea beyond that, I thought it better to leave it for a specialist. But at this point, I'm bringing it what I know...

     

    The answer really depends on what you're talking about in your question.

     

    Speaking of Outlook COM Add-ins pre-VSTO 2005 vs VSTO Add-ins, I'm going to type out some text from page 944 of "Visual Studio Tools for Office". Note that I have no experience with this, I'm just quoting and hope this answers your question. It appears no experienced Outlook folks are around this week (Sue Mosher, for example). If you want to discuss this in more detail I recommend visiting some of the newsgroup links listed in the Please Read First message, where you'll find many more Outlook specialists.

     

    "Outlook COM  add-in development requires you to track any variables set to Outlook objects, sind the Close events of the Inspector and Explorerer objects, set your vairables set to Outllok object to null when the last Inspector or Explorer closes or the Application object's Quit event is raised, and force two garbage collections. This complexity is not required when building add-ins for other Office applications, so do nto apply these techniques to Excel or Word. Excle and Word are more robust to reference counts on their COM objects being held during the shutting down of the applications. This situation also never occurs in VSTO 2005 customizations because of VSTO's better model for loading and unloading code.

     

    If you use the VSTO Outlook add-in project, you will not have to worry about any of these Outlook-specific shutdown problems or any of the problems that we said requried a *** in Chapter 23. The VSTO Outlook add-in project uses the VSTO mdoel for loading and unloading an add-in. The VSTO model alsways loads a customization into its own application domain. When the add-in is unloaded or the application exits, VSTO raises a Shutdown even tinto the customization. The developer does not have to set any objects to null or force a garbage collection to clean up RCWs because once the Shutdown event handler has been run, VSTO unloads the application domain associated with the customization..."

    Wednesday, August 6, 2008 9:24 AM
    Moderator
  • Hi,

     

    If you are just asking about cleanup at shutdown, then yes, the VSTO Runtime will generally take care of you.  We use AppDomain isolation for all types of customizations, so when the AppDomain is torn down, cleanup will occur,  One of the consequences of tearing down an AppDomain is that the Common Language Runtime (CLR) will execute finalization on *all* finalizable objects in the doomed AppDomain (regardless of whether they are rooted).  This means that all Runtime Callable Wrappers (RCWs) will be forced to release their COM references when the AppDomain unloads.  It is possible (however rare), that the finalizer thread can get blocked indefinitely.  If that happens, the CLR will have to abort finalization and any RCWs that have yet to be finalized will orphan their COM objects.  As I said, this would be extremely rare (likely due to a bug in a component's finalization code), so you may not find it worth considering.

     

    However, you may still be forced to think about explicit lifetime management of your COM objects for performance reasons.  The fundamental problem is that RCWs are relatively small objects, while the COM objects that they manage may be large.  Depending on what your Add-in does, you may not be able to wait for the generation 0 GC heap to fill up (which would force finalization on eligible RCWs, triggering the IUnknown::Release call).  IOW, your add-in might be creating COM objects at an undesirable rate, creating unnecessary memory pressure and hurting performance.  In that situation, you will need to choose a strategy to explicitly release your COM objects.

     

    My recommendation would be to run perfmon and watch what happens to process private bytes while your add-in is running under various usage cases.  Private bytes represent the total amount of memory that the process has allocated.  The question will be to what extent private bytes grow (and the impact on performance) before they shrink again when the generation 0 heap finally fills and the system automatically performs a GC.  What you are trying to avoid is a situation where your add-in consumes so much physical memory that you start triggering hard page-faults.  If memory usage gets large, start looking at process page faults per second, as well as what is happening with the physical hard disk. If page faults and reads start jumping, then you know you have a performance problem which you will want to address by engaging in an explicit release strategy to limit the amount of memory that your add-in consumes.

     

    In terms of explicit release strategies, they are pretty well summed up in the blog entries that Ji mentions.  However, I do want to point out that setting an object to null simply makes it eligible for GC; it does not result in any memory being freed or any finalizers being run.

     

    Sincerely,

     

    Geoff Darst

    Microsoft VSTO Team

     

    Wednesday, August 6, 2008 3:53 PM
    Answerer
  •  

    Thanks to everyone, your responses are very helpful and they answered my questions completely.
    Thursday, August 7, 2008 7:45 AM
  •  

    Geoff,

    I know it has been a while since you last commented on this forum; however, if you are still around I would like to know if you could shed some light on a particular concern of mine.  Your recommendations are good and sound, I am just wondering if you have considered the following KB article:

    http://support.microsoft.com/kb/830829

    Essentially, in Exchange Server, the number of server-side objects that are allowed by clients is limited to prevent a single client from the exhausting resources on the Exchange server.   I have written an Outlook VSTO add-in and in some areas of code the add-in is able to reach these Exchange limits if Outlook is not using cached-exchange mode if a garbage collection is not performed to release the COM objects.  Usually this is in situations where we are iterating through an attachment collection or an items collection.  This leads to Outlook complaining with errors like “Your server administrator has limited the number of items you can open simultaneously.” 

    Would your recommendation be that I try to isolate those areas of code which can be susceptible to this problem and make sure I am deterministically releasing the COM objects using Marshal.ReleaseComObject/Marshal.FinalReleaseComObject or would you recommend something else?  Do both Marshal.ReleaseComObject  and Marshal.FinalReleaseComObject immediately release the COM object if the reference count becomes zero, or does this happen later on by the garbage collector as a result of these calls?

    One of my concerns is that some customers, depending on their usage pattern of Outlook, might cause another area of code we haven’t accounted for to reach one of the Exchange server-side object limits.    In some ways, unless all COM objects are explicitly being released deterministically, we have no way to be sure that customers won’t hit the limits with our software although we could assume that they won’t send for instance more than 250 messages before a garbage collection occurs.  On the otherhand, when you have an add-in with a fair amount of code it is a difficult task and complicates the code using Marshal.ReleaseComObject/Marshal.FinalReleaseComObject all over the place with the try/catch/finally blocks etcetera.   I don’t believe that would be a recommended practice unless perhaps your code-base was small.  If we were to go this route I suppose it would be a matter of using some more interesting .NET language features like extension methods, lambda predicates, or IDisposable to simplify the handling of this.

    What are your thoughts?

     

    -Mark





    Monday, July 25, 2011 10:23 PM