DirectoryEntry Disposal Test

  • Thread starter Thread starter cameron
  • Start date Start date
C

cameron

I am in a situation in which I am recieving a DirectoryEntry that may or
may not be already be disposed. I need a very fast, (from a code point
of view not necissarily a coding point of view), way of testing if it
has been disposed.

Currently I have:

try
{
string Junk MyDirectoryEntry.Guid.ToString();
}
catch
{
// it has been disposed of, put logic here
}

This is so painfully slow. The 1 line in the try take .00450 seconds and
that of course is not acceptable. Does anyone have a nicer way of
testing for this condition?

-Cam
 
Well, DirectoryEntry has a private bool field called disposed. You could use
reflection to get that out. I'd imagine that'd be faster than throwing an
exception.

And, AFAIK, if the property cache is filled, then getting the guid might not
throw an exception.

-mike
MVP
 
cameron said:
I am in a situation in which I am recieving a DirectoryEntry that may or
may not be already be disposed. I need a very fast, (from a code point
of view not necissarily a coding point of view), way of testing if it
has been disposed.

Currently I have:

try
{
string Junk MyDirectoryEntry.Guid.ToString();
}
catch
{
// it has been disposed of, put logic here
}

This is so painfully slow. The 1 line in the try take .00450 seconds and
that of course is not acceptable. Does anyone have a nicer way of
testing for this condition?

Looking at the Directory Entry class with Lutz Roeder's Reflector, it
appears that the Guid property doesn't test for the object being
disposed. In other words, your method won't give you the results you
want regardless of its speed.

The Name property does check for the object being disposed (indirectly).
I have no idea how fast or slow it is. Note that in the case where
the object is disposed, the test will be slow because of the exception.
Hopefully for non-disposed objects, the Name property will be pretty quick.

AS far as the suggestion for using reflection to test the private
'disposed' field, that should work, but I'm guessing that it's not very
fast, and depending on how your application is deployed you might have
problems with code access security.
 
Looking at the Directory Entry class with Lutz Roeder's Reflector, it
appears that the Guid property doesn't test for the object being disposed.
In other words, your method won't give you the results you want regardless
of its speed.

The Name property does check for the object being disposed (indirectly). I
have no idea how fast or slow it is. Note that in the case where the
object is disposed, the test will be slow because of the exception.
Hopefully for non-disposed objects, the Name property will be pretty
quick.

Well, the Guid does get it checked, again indirectly. Essentially every
property will, if it's not already cached. Calling a method that definately
forces it (such as RefreshCache or likewise) will guarantee it.
AS far as the suggestion for using reflection to test the private
'disposed' field, that should work, but I'm guessing that it's not very
fast, and depending on how your application is deployed you might have
problems with code access security.

Yea, it's slow, but I doubt it's slower than catching an exception, at least
in the fail case (I dont know the average test case, so it's hard to know
what to optimize for). If one more person cares, I'll go do some benchmarks
:).

Also, reflecting on a private field is a poor, breakable, hack. Just thought
I'd mention that.

-mike
MVP
 
Michael said:
Well, the Guid does get it checked, again indirectly. Essentially every
property will, if it's not already cached. Calling a method that
definately forces it (such as RefreshCache or likewise) will guarantee it.

On second look, it does appear that the Guid property does potentially
call Bind() (the private method that actually checks whether the object
is disposed). But it looks like there is some chance that Bind() might
not be called (as you say, depending on whether the information is
cached). The Name property unconditionally calls the Bind() method.
Also, reflecting on a private field is a poor, breakable, hack. Just
thought I'd mention that.

Depending on the undocumented behavior of the properties is also
breakable (although accessing a property on a disposed object should
cause an exception).

The original poster might consider simply wrapping the entire processing
of the DirectoryEntry in a try/catch, and just do whatever processing he
intends to do, with no special test for a disposed object. Let the big
try/catch deal with the disposed objects; that way the processing only
takes a hit when called with a reference to an already disposed
DirectoryEntry.
 
The original poster might consider simply wrapping the entire processing
of the DirectoryEntry in a try/catch, and just do whatever processing he
intends to do, with no special test for a disposed object. Let the big
try/catch deal with the disposed objects; that way the processing only
takes a hit when called with a reference to an already disposed
DirectoryEntry.

Or register references to the disposed objects in some kind of collection.
But then again, if he has access to them when they are getting disposed,
then he might be able to just redesign this part of the app :).

-mike
MVP
 
Basically Is see two options:
1) Implement the DirectoryEntry.Disposed eventhandler, in which you set a
flag ( f.i IsDisposed) you can check before using the DirectoryEntry object.
2) Put all your processing in a using block.

Willy.
 
The "real" cache is contained in the unmanaged code portion (ADSI COM
object) as an unmanaged memory resource, but as the DirectoryEntry object is
disposed off, so is the reference to the underlying COM object reference.
Now the (managed) property data only reflects a part of the cached ADSI
data, so it wouldn't be wise to access this data once the object is
disposed.
Therefore, System.ObjectDisposedException is thrown on you when you try to
access the DirectoryEntry object reference.

Willy.
 
Back
Top