다음을 통해 공유


Getting SharePoint Event IDs “90hv” and “nask” Despite Disposing Just Fine

Most SharePoint developers will have probably have seen these SharePoint event IDs at some point or other, especially if you’ve ever worked with server-side code before. How to properly manage server-side SharePoint objects is pretty well documented already, but I’ve found it’s still easy to reproduce these “errors” even with good clean-up logic in code.

I’ve seen this a couple of times where technically the developer isn’t doing something wrong but SharePoint cries anyway. Why? Let’s find out.

Standard Coding Practise – Awesome Helper Functions

Consider this simple example of a button that reads the number of items in a list, using the return results of our very own helper function, “GetItems” (not to be confused with SPList.GetItems):

image

This design is nice because our “GetItems” can be all generic and awesome, and we just implement it like the good developers we’ve been brought-up to be. This will “work” but SharePoint will complain in mysterious ways anyway...What’s the problem? We’re cleaning up both the SPWeb and SPSite as we’re supposed to but we’ll get a memory-leak anyway. Why?

The Problem – Premature Memory Clean-up

This code would generate this mysterious error (event ID “90hv”):

{GUID} Stack trace:

at Microsoft.SharePoint.SPListItemCollection.EnsureListItemsData()

at Microsoft.SharePoint.SPListItemCollection.get_Count()

at MyClass.btnExecute_Click(Object sender, EventArgs e)

…and a warning about “an SPRequest object was not disposed before the end of this thread” to boot, despite everything actually working; no exceptions or anything. Why complain then?

The problem is fairly simple actually. In parent method “btnExecute_Click” we’re reading “listItems.Count” – a count of the list-item-collection of what “GetItems” returned, for some label. When you read almost anything with SharePoint data objects, that read will almost always call “SPListItemCollection.EnsureListItemsData” to make sure nothing’s changed in the dataset since loading them, but the problem is that we’ve just closed the SPRequest that was used to get the list-items. Why has the SPRequest closed? Well because we cleaned-up the SPWeb & SPSite we used to load the data from because we're now past our "using" block.

So what happens if we don't have the original SPRequest? Simple really; SharePoint has to open a new SPRequest (which will impact performance, btw) to run “EnsureListItemsData” instead of using the old exsiting one. Amusingly though, it doesn’t then clean up properly its own created SPRequest so subsequently complains “someone can’t program, don’t you know”, which is what these errors actually come from.

Yes folks, you understood right; SharePoint complains about its own memory management in these circumstances! Don’t hold your breath on a fix though, because, if you dear developer weren’t so trigger-happy on memory disposing we wouldn’t be seeing these mysterious messages in the first place :)

The Solution – Code Redesign

It’s pretty simple really; make sure you don’t use your SPListItemCollection once you’ve cleaned-up the SPWeb & SPSite. Sure that might take some redesign, and depending on how much code is written this way will depend on how long it’ll take to achieve.

Here’s how I would write the above code with this advice in mind:

image

With this redesign there’s no way the parent function would ever accidentally invoke any SharePoint data-reads at this point and therefore no further SPRequests are needed. SharePoint logs will be much cleaner!

Why bother redesigning code so we don’t accidently make extra SPRequests?

  1. Cleaner SharePoint logs. Why care? Try and find the root cause of something truly severe, when every single GET request is filling the ULS with these messages of doom even on a good day.
  2. Better performance – allocating new SPRequests is expensive, and in this case unnecessary. If your performance is bad this may be one reason why.

I hope this helped!

 

Cheers,

// Sam Betts