Additional Little-Known SharePoint Dispose Guidelines
Our SharePoint Audit product is no longer available. Instead, please check out this alternative product from our sister company: Aquaforest CheckPoint.
If you have been a SharePoint developer for more than a day, it will come as no surprise that you need to take great care of manually disposing your objects. Much has been written on this subject, but there are still gaps in the SharePoint Community’s knowledge.
A couple of weeks ago we identified an undocumented requirement to call Dispose() on SPFile streams and today we are documenting a resource leak related to SharePoint’s fancy SiteAdministrationSelector class, which allows users of our Audit Suite to quickly switch between the audit logs for different Site Collections.
During our latest test cycle we were seeing the following line in our SharePoint Trace Logs every time our Audit Log Viewer was invoked, even when the SiteAdministrationSelector was hidden or disabled:
An SPRequest object was not disposed before the end of this thread. To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it. Due to flags specified at object creation, this will not be freed until processed by garbage collection. Allocation Id: {F4F8B307-1F2C-4925-9C23-2A1EBED4B475} To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings. Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.”
As we are avid users of SPDisposeCheck we were pretty sure we were not leaking any obvious SPSite or SPWeb resources. We tried explicitly disposing the SiteAdministrationSelector in the OnUnload event, but no luck. After several more, and increasingly desperate, attempts we found out that the object that requires disposing is the CurrentItem property, leaving us with the following OnUnload event.
protected override void OnUnload(EventArgs e) { try { // ** Dispose the selected site in the selector. See bug #373 if(siteCollectionSelector.CurrentItem != null) siteCollectionSelector.CurrentItem.Dispose(); // ** Dispose our global objects if (_selectedSite != null && _disposeSelectedSite == true) _selectedSite.Dispose(); if (_selectedWeb != null && _disposeSelectedWeb == true) _selectedWeb.Dispose(); } catch (Exception ex) { ExceptionHelper.ProcessException(ex, this); } }
Additional topics regarding the prevention of resource leaks in SharePoint are discussed in section 7.11 of our SharePoint development guidelines. Download your free copy here.