Matthew Rodatus
Matthew Rodatus

Reputation: 1461

Is it appropriate to use GC.AddMemoryPressure to trigger more frequent Runtime Callable Wrapper (RCW) finalization?

My .NET application is using very high numbers of RCWs in a very short period of time (thousands of RCWs in less than a second). I am able to gauge this behavior with the following performance counters: - Process -> Handle Count - .NET CLR Memory -> # of Sink Blocks in use

We have correctly implemented IDisposable wrapper objects around the RCWs; we call Marshal.FinalReleaseComObject on the various RCWs, and in the appropriate order.

According to this blog post, the COM object underlying an RCW is not actually cleaned up until the RCW is finalized.

Is it appropriate to use GC.AddMemoryPressure to force the GC to clean up our RCWs more quickly to prevent out of memory errors?

Upvotes: 2

Views: 245

Answers (1)

Eric J.
Eric J.

Reputation: 150148

You should maintain an explicit managed reference to each COM object, and call Marshal.ReleaseComObject as soon as the COM object is no longer needed.

This method is used to explicitly control the lifetime of a COM object used from managed code. You should use this method to free the underlying COM object that holds references to resources in a timely manner or when objects must be freed in a specific order.

Note that using "double dots" causes the runtime to create hidden managed references, e.g. a common pattern in Excel:

Worksheet sheet = excelApp.Worksheets.Open(sheetName);

creates a hidden managed object that wraps Worksheets. The preferred method would be

Worksheets sheets = excelApp.Worksheets; 
Worksheet sheet = sheets.Open(sheetName);

You would call Marshal.ReleaseComObject on each of those managed variables, in the reverse order they were created.

If you do have hidden references to COM objects, the only reliable method to dispose of them that I have seen is

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

Upvotes: 2

Related Questions