When do I need to call ReleaseComObject?

2019-03-13 10:44发布

In a Microsoft Office AddIn we are passed COM objects in events. To take a specific case, when Word opens a document we are called and passed a Document object. So when do we need to call Marshal.ReleaseComObject()?

  1. If we access the Document object do we need to call release on it? Or can we assume Word has already accessed it and will clean it up?
  2. If we access Document.Name that gives us a string. As a string is not a COM object we do not need to clean that up - correct?
  3. But if we access any member that returns a class that is wrapping a COM object (which is any class returned by a member method/function), we do need to call release on that - correct?

And what happens if we miss a release? Any COM object we hold onto for an indeterminate amount of time we wrap in a class of ours with IDisposable implemented. We call Dispose() when we're done. But some of the code handling this is complex and I'm guessing we have an occasional case where we're not calling Dispose.

Are we better off having a finalizer which then adds overhead for every single instance of these objects (a lot!)? Or are we better off with a small number of Word COM objects that are never released?

thanks - dave

1条回答
Deceive 欺骗
2楼-- · 2019-03-13 10:56

In short, every reference you make to a COM object must be released. If you don't, the process will stay in memory.

That excludes value types (strings, etc.) and child COM objects you have not explicitly referenced.

One exception may be COM objects passed to you as event parameters. I don't think you need to release them but I'm not certain. However a quick test should confirm that. (Try your add-in with and without releasing the COM object. See if the add-in begins to behave funny or if any related processes are left running after the app is closed.)

To address your specific questions:

  1. If we access the Document object do we need to call release on it? Or can we assume Word has already accessed it and will clean it up? -- You must release it.

  2. If we access Document.Name that gives us a string. As a string is not a COM object we do not need to clean that up - correct? -- You don't need to clean up value types.

  3. But if we access any member that returns a class that is wrapping a COM object (which is any class returned by a member method/function), we do need to call release on that - correct? -- You don't need to release it if you haven't explicitly referenced it. (There are some exceptions. For example in this question of mine I discovered that a particular COM method was instantiating a COM object and never releasing it. Since I have no control over the method implementation my only choice was to avoid using the method.)

  4. And what happens if we miss a release? -- The process (winword.exe, excel.exe, etc.) will remain in memory. Over time all of these unterminated processes will eat up all of the available memory on the machine.

  5. Are we better off having a finalizer which then adds overhead for every single instance of these objects (a lot!)? Or are we better off with a small number of Word COM objects that are never released? -- You're better off with the finalizer. Always release your COM objects! I've found that the steps outlined here are the most effective. (These steps use FinalReleaseComObject which is preferred over ReleaseComObject.) I also advise against killing the Office process as an alternative to not releasing COM. Over time this will cause issues with the Office interop (which I've never fully understood).

查看更多
登录 后发表回答