.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

To Dispose or Not To Dispose... For the xxxth Time

8 REPLIES 8
Reply
Message 1 of 9
Anonymous
939 Views, 8 Replies

To Dispose or Not To Dispose... For the xxxth Time

I'm fed up with this. Maybe I just haven't got it yet, but I think this
is ridiculous. Can we please nail down exactly when to or not to Dispose().

I've studied, read carefully word for word, and then revisited multiple
times numerous opinions on this, especially those posted by Kean and
Tony. Still I'm being plagued by problems which I believe boil down to
Dispose().

Here's what I've got:
1. Not DBObject - [1] Either
2. DBObject, no Database - [1] Yes, but [2] Either (Yes Advised)
3. DBObject, in Database, in Transaction - [1,3] Either
4. DBObject, in Database, no Transaction - [2,3] Yes
5. With "Deterministic Destructor Semantics"
(DocumentLock, Transaction, DBObject) - [3] Yes
6. Created Object - [3] Yes
7. Returned Object - [3] Depends
8. ResultBuffer - [3] Either, but comments at [4] (Wyatt, Kean, 03,
04Apr07) maybe Yes
9. Aggregates, collection members, no constructor (Document) - [5] No
10. DBObjectCollection - [6] Either, but [7] Yes
11. Anything referencing other DBObjects in Database
(DBObjectCollection) - speculation on [7] Yes

[1]
http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
[2]
http://discussion.autodesk.com/forums/thread.jspa?messageID=5902684ᅜ
[3]
http://discussion.autodesk.com/forums/message.jspa?messageID=5736485#5736485
[4]
http://through-the-interface.typepad.com/through_the_interface/2007/04/adding_xdata_to.html
[5]
http://discussion.autodesk.com/forums/message.jspa?messageID=5101329#5101329
[6]
http://discussion.autodesk.com/forums/thread.jspa?messageID=6132777鐩
[7] Attached code yields "FATAL ERROR: Unhandled Access Violation
Reading 0x7ed33331c Exception
at 62064bb3h" or similar on closing AutoCAD. Uncomment Dispose() and no
error. Is this not a Dispose() problem and there is something else I'm
missing? I stumbled onto it trying to track down something else.
WinXP, Acad2008, VSE2005.

What am I still missing? Please enlighten me.

Thanks,

--
James Allen
Malicoat-Winslow Engineers, P.C.
Columbia, MO
8 REPLIES 8
Message 2 of 9
Anonymous
in reply to: Anonymous

And here is the attachment, zipped and hopefully not mangled this time.

James


James Allen wrote:
> I'm fed up with this. Maybe I just haven't got it yet, but I think this
> is ridiculous. Can we please nail down exactly when to or not to Dispose().
>
> I've studied, read carefully word for word, and then revisited multiple
> times numerous opinions on this, especially those posted by Kean and
> Tony. Still I'm being plagued by problems which I believe boil down to
> Dispose().
>
> Here's what I've got:
> 1. Not DBObject - [1] Either
> 2. DBObject, no Database - [1] Yes, but [2] Either (Yes Advised)
> 3. DBObject, in Database, in Transaction - [1,3] Either
> 4. DBObject, in Database, no Transaction - [2,3] Yes
> 5. With "Deterministic Destructor Semantics"
> (DocumentLock, Transaction, DBObject) - [3] Yes
> 6. Created Object - [3] Yes
> 7. Returned Object - [3] Depends
> 8. ResultBuffer - [3] Either, but comments at [4] (Wyatt, Kean, 03,
> 04Apr07) maybe Yes
> 9. Aggregates, collection members, no constructor (Document) - [5] No
> 10. DBObjectCollection - [6] Either, but [7] Yes
> 11. Anything referencing other DBObjects in Database
> (DBObjectCollection) - speculation on [7] Yes
>
> [1]
> http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
> [2]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=5902684ᅜ
> [3]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5736485#5736485
> [4]
> http://through-the-interface.typepad.com/through_the_interface/2007/04/adding_xdata_to.html
> [5]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5101329#5101329
> [6]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=6132777鐩
> [7] Attached code yields "FATAL ERROR: Unhandled Access Violation
> Reading 0x7ed33331c Exception
> at 62064bb3h" or similar on closing AutoCAD. Uncomment Dispose() and no
> error. Is this not a Dispose() problem and there is something else I'm
> missing? I stumbled onto it trying to track down something else.
> WinXP, Acad2008, VSE2005.
>
> What am I still missing? Please enlighten me.
>
> Thanks,
>
> --
> James Allen
> Malicoat-Winslow Engineers, P.C.
> Columbia, MO
>
Message 3 of 9
Anonymous
in reply to: Anonymous

I haven't investigated why AutoCAD crashes if you Dispose() the
DBObjectCollection. It could be a bug.

Regardless of that, the fact is that a DBObjectCollection does not have to
be disposed, but the DBObjects it contains *may* need to be disposed
determinstically, depending on the rules for disposing DBObjects. IOW,
depending on whether they are database-resident or transaction-resident.

In other words, there's nothing special about a DBObjectCollection as it
relates to disposition of the elements it contains and in that regards, a
DBObjectCollection behaves no differently than a List.

A DBObject must be disposed deterministically, if any of the following are
true:

1. The DBObject is not database-resident, typically these are instances
of DBObjects that were created via their new() constructor and have not been
appended to a database. There are a number of APIs that create and return
one or more new objects that are not database-resident (they leave it up to
to add them to a database if you chose). An example is the Entity's
Explode() method, which requires you to pass it a DBObjectCollection, to
which it adds the new entities it creates by exploding the object the method
is invoked on.

2. The DBObject is not transaction-resident (e.g., acquired via the
ObjectId.Open() method, which opens objects directly rather than in a
transaction). ObjectId.Open is marked as 'advanced', and should only be used
in very specialized cases (e.g., where performance is critical).
ObjectId.Open is the managed counterpart of the acdbOpenAcDbObject() native
API. In the case of non-transaction-resident DBObjects, calling Dispose() on
one always results in a call to the DBObject's Close() method, which *must*
happen if you don't want a failure. Alternately, you can explicitly call
either the Close() or Cancel() method on a non-transaction-resident
DBObject, and once you've done so, you no longer need to call Dispose().

DBObjects that are passed in the arguments of event handlers should never be
disposed.

The ObjectId.GetObject() method is really just another way of calling
GetObject() on the top transaction (hence, it requires an active
transaction), so the resulting object is always transaction-resident.

In the case of your code, GetAllObjects() returns all objects that are open
in all active transactions, which of course, means that all returned objects
should be transaction-resident and hence, do not need to be
deterministically disposed.

I agree completely with your frustration over the Dispose() enigma, because
it certainly is confusing, and IMO, needlessly so.

That's a result of what I believe is a less-than-optimal API design, where
just about everything that wraps a native API is a descendent of a type
called 'DisposableWrapper' (the class that implements IDisposable).

And as you've noted, in some cases the wrappers do not need to be
determinstically disposed, and in a few cases, must *never* be.

The bottom line here insofar as DBObjectCollection goes, is that you do not
need to be concerned with disposing a DBObjectCollection, but you must be
concerned with disposing the DObjects it contains (because the containing
DBObjectCollection does not do that for you), according to the
aforementioned guidelines. In this specific case, since all of the objects
in the DBObjectCollection are transaction-resident, you don't have to
dispose them, and obviously there is a problem if you do call Dispose() on
the DBObjectCollection, but I haven't looked at that so can't tell you much
about it.

Additionally, whenever you do dispose of the objects in a
DBObjectCollection, you should probably also call its Clear() method before
you finish using the collection.


--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


"James Allen" wrote in message
news:6160576@discussion.autodesk.com...
And here is the attachment, zipped and hopefully not mangled this time.

James


James Allen wrote:
> I'm fed up with this. Maybe I just haven't got it yet, but I think this
> is ridiculous. Can we please nail down exactly when to or not to
> Dispose().
>
> I've studied, read carefully word for word, and then revisited multiple
> times numerous opinions on this, especially those posted by Kean and
> Tony. Still I'm being plagued by problems which I believe boil down to
> Dispose().
>
> Here's what I've got:
> 1. Not DBObject - [1] Either
> 2. DBObject, no Database - [1] Yes, but [2] Either (Yes Advised)
> 3. DBObject, in Database, in Transaction - [1,3] Either
> 4. DBObject, in Database, no Transaction - [2,3] Yes
> 5. With "Deterministic Destructor Semantics"
> (DocumentLock, Transaction, DBObject) - [3] Yes
> 6. Created Object - [3] Yes
> 7. Returned Object - [3] Depends
> 8. ResultBuffer - [3] Either, but comments at [4] (Wyatt, Kean, 03,
> 04Apr07) maybe Yes
> 9. Aggregates, collection members, no constructor (Document) - [5] No
> 10. DBObjectCollection - [6] Either, but [7] Yes
> 11. Anything referencing other DBObjects in Database
> (DBObjectCollection) - speculation on [7] Yes
>
> [1]
> http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
> [2]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=5902684ᅜ
> [3]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5736485#5736485
> [4]
> http://through-the-interface.typepad.com/through_the_interface/2007/04/adding_xdata_to.html
> [5]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5101329#5101329
> [6]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=6132777鐩
> [7] Attached code yields "FATAL ERROR: Unhandled Access Violation
> Reading 0x7ed33331c Exception
> at 62064bb3h" or similar on closing AutoCAD. Uncomment Dispose() and no
> error. Is this not a Dispose() problem and there is something else I'm
> missing? I stumbled onto it trying to track down something else.
> WinXP, Acad2008, VSE2005.
>
> What am I still missing? Please enlighten me.
>
> Thanks,
>
> --
> James Allen
> Malicoat-Winslow Engineers, P.C.
> Columbia, MO
>
Message 4 of 9
Anonymous
in reply to: Anonymous

Did you actually test the code you posted, or was there more to the code
that was actually crashing?

I ask because I cannot reproduce the crash here (on AutoCAD 2010).

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


"James Allen" wrote in message
news:6160576@discussion.autodesk.com...
And here is the attachment, zipped and hopefully not mangled this time.

James


James Allen wrote:
> I'm fed up with this. Maybe I just haven't got it yet, but I think this
> is ridiculous. Can we please nail down exactly when to or not to
> Dispose().
>
> I've studied, read carefully word for word, and then revisited multiple
> times numerous opinions on this, especially those posted by Kean and
> Tony. Still I'm being plagued by problems which I believe boil down to
> Dispose().
>
> Here's what I've got:
> 1. Not DBObject - [1] Either
> 2. DBObject, no Database - [1] Yes, but [2] Either (Yes Advised)
> 3. DBObject, in Database, in Transaction - [1,3] Either
> 4. DBObject, in Database, no Transaction - [2,3] Yes
> 5. With "Deterministic Destructor Semantics"
> (DocumentLock, Transaction, DBObject) - [3] Yes
> 6. Created Object - [3] Yes
> 7. Returned Object - [3] Depends
> 8. ResultBuffer - [3] Either, but comments at [4] (Wyatt, Kean, 03,
> 04Apr07) maybe Yes
> 9. Aggregates, collection members, no constructor (Document) - [5] No
> 10. DBObjectCollection - [6] Either, but [7] Yes
> 11. Anything referencing other DBObjects in Database
> (DBObjectCollection) - speculation on [7] Yes
>
> [1]
> http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
> [2]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=5902684ᅜ
> [3]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5736485#5736485
> [4]
> http://through-the-interface.typepad.com/through_the_interface/2007/04/adding_xdata_to.html
> [5]
> http://discussion.autodesk.com/forums/message.jspa?messageID=5101329#5101329
> [6]
> http://discussion.autodesk.com/forums/thread.jspa?messageID=6132777鐩
> [7] Attached code yields "FATAL ERROR: Unhandled Access Violation
> Reading 0x7ed33331c Exception
> at 62064bb3h" or similar on closing AutoCAD. Uncomment Dispose() and no
> error. Is this not a Dispose() problem and there is something else I'm
> missing? I stumbled onto it trying to track down something else.
> WinXP, Acad2008, VSE2005.
>
> What am I still missing? Please enlighten me.
>
> Thanks,
>
> --
> James Allen
> Malicoat-Winslow Engineers, P.C.
> Columbia, MO
>
Message 5 of 9
Anonymous
in reply to: Anonymous

Hi Tony,

Thank you for the replies. Yes, I tested it several times as posted, in
2008. The only 2009 I have loaded right now is MEP. I didn't want to
mix it up too much with that. And I haven't loaded 2010 yet at all.
Perhaps it is something they have fixed in subsequent versions. I'll
see if I can get those loaded (something I need to do anyway) and check
results there.

I had figured that ObjectId.GetObject was equivalent to
TransactionManager.GetObject or [top]Transaction.GetObject. I did also
test using the two latter just in case though, and also with different
user profiles (one clean Acad default). In the several times I tested
the error message on close was identical (or nearly, in the case of the
Acad profile). The first time I tried with tm.GetObject it did not
error, but then I tried again with it the same and got the same error as
the other times. That was the only time it did not error on close.

--
James Allen
Malicoat-Winslow Engineers, P.C.
Columbia, MO



Tony Tanzillo wrote:
> Did you actually test the code you posted, or was there more to the code
> that was actually crashing?
>
> I ask because I cannot reproduce the crash here (on AutoCAD 2010).
>
>
Message 6 of 9
Anonymous
in reply to: Anonymous

Regarding that dispose rule-list, I would make the following edits based
on what I hear you saying:

10. DBObjectCollection - [Either. But there may be a bug.]
11. Anything referencing other DBObjects in Database
(DBObjectCollection) - [Either, see 10]
12. DBObject argument of event handler - No

Aside from it being grossly oversimplified relative to the subject (hence the links to more discussion), do you see anything else missing or wrong in that list.

--
James Allen
Malicoat-Winslow Engineers, P.C.
Columbia, MO



Tony Tanzillo wrote:
> I haven't investigated why AutoCAD crashes if you Dispose() the
> DBObjectCollection. It could be a bug.
>
> Regardless of that, the fact is that a DBObjectCollection does not have to
> be disposed, but the DBObjects it contains *may* need to be disposed
> determinstically, depending on the rules for disposing DBObjects. IOW,
> depending on whether they are database-resident or transaction-resident.
>
> In other words, there's nothing special about a DBObjectCollection as it
> relates to disposition of the elements it contains and in that regards, a
> DBObjectCollection behaves no differently than a List.
>
> A DBObject must be disposed deterministically, if any of the following are
> true:
>
> 1. The DBObject is not database-resident, typically these are instances
> of DBObjects that were created via their new() constructor and have not been
> appended to a database. There are a number of APIs that create and return
> one or more new objects that are not database-resident (they leave it up to
> to add them to a database if you chose). An example is the Entity's
> Explode() method, which requires you to pass it a DBObjectCollection, to
> which it adds the new entities it creates by exploding the object the method
> is invoked on.
>
> 2. The DBObject is not transaction-resident (e.g., acquired via the
> ObjectId.Open() method, which opens objects directly rather than in a
> transaction). ObjectId.Open is marked as 'advanced', and should only be used
> in very specialized cases (e.g., where performance is critical).
> ObjectId.Open is the managed counterpart of the acdbOpenAcDbObject() native
> API. In the case of non-transaction-resident DBObjects, calling Dispose() on
> one always results in a call to the DBObject's Close() method, which *must*
> happen if you don't want a failure. Alternately, you can explicitly call
> either the Close() or Cancel() method on a non-transaction-resident
> DBObject, and once you've done so, you no longer need to call Dispose().
>
> DBObjects that are passed in the arguments of event handlers should never be
> disposed.
>
> The ObjectId.GetObject() method is really just another way of calling
> GetObject() on the top transaction (hence, it requires an active
> transaction), so the resulting object is always transaction-resident.
>
> In the case of your code, GetAllObjects() returns all objects that are open
> in all active transactions, which of course, means that all returned objects
> should be transaction-resident and hence, do not need to be
> deterministically disposed.
>
> I agree completely with your frustration over the Dispose() enigma, because
> it certainly is confusing, and IMO, needlessly so.
>
> That's a result of what I believe is a less-than-optimal API design, where
> just about everything that wraps a native API is a descendent of a type
> called 'DisposableWrapper' (the class that implements IDisposable).
>
> And as you've noted, in some cases the wrappers do not need to be
> determinstically disposed, and in a few cases, must *never* be.
>
> The bottom line here insofar as DBObjectCollection goes, is that you do not
> need to be concerned with disposing a DBObjectCollection, but you must be
> concerned with disposing the DObjects it contains (because the containing
> DBObjectCollection does not do that for you), according to the
> aforementioned guidelines. In this specific case, since all of the objects
> in the DBObjectCollection are transaction-resident, you don't have to
> dispose them, and obviously there is a problem if you do call Dispose() on
> the DBObjectCollection, but I haven't looked at that so can't tell you much
> about it.
>
> Additionally, whenever you do dispose of the objects in a
> DBObjectCollection, you should probably also call its Clear() method before
> you finish using the collection.
>
>
>
Message 7 of 9
Anonymous
in reply to: Anonymous

I don't think you can generalize or distill this down to a list of rules.

If a DBObjectCollection (or even just an array of DBObjects) contains
DBObjects that are not database-resident, and there are no other references
to those objects anywhere else (e.g., no variables referencing the same
objects), then the 'rule' is that you must call Dispose() on the non
database-resident DBObjects in the collection/array *before* the
collection/array itself is disposed or becomes unreferenced/unreachable.

That's because calling Dispose() or Clear() on a DBObjectCollection or other
container/collection type that contains references to DBObjects, results in
those DBObjects becoming 'unreachable'.

So, let's suppose you have a DBObjectCollection that contains a single
DBObject, and you have no other variables that reference that same DBObject.

Further, suppose that the single DBObject in the DBObjectCollection is not
database-resident. Because DBObjects that are not database-resident must be
deterministically disposed, you must call Dispose() on that DBObject
*before* you
call Dispose() or Clear() on the DBObjectCollection that contains it.

You must do that because once the DBObjectCollection no longer references
the DBObject, it becomes unreachable and elegible for finalization, and if
it is finalized before you call Dispose() on it, AutoCAD will crash.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm
Message 8 of 9
Anonymous
in reply to: Anonymous

Understood. Thank you for that additional clarification, Tony.

James


Tony Tanzillo wrote:
> I don't think you can generalize or distill this down to a list of rules.
>
> [etc.]
Message 9 of 9
Anonymous
in reply to: Anonymous

"...as posted..." Except for renaming "Class1" to "DisposeTest".
Sorry, didn't mean to lie.

I also tested with 2008 on a different machine (with a different OS) and
got the same result. I've now tested 2007-10 in the original
environment and it seems that this was a bug that was resolved as of 2009.

--
James Allen
Malicoat-Winslow Engineers, P.C.
Columbia, MO



James Allen wrote:
> Hi Tony,
>
> Thank you for the replies. Yes, I tested it several times as posted, in
> 2008. The only 2009 I have loaded right now is MEP. I didn't want to
> [etc.]

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost