Hi,
I have also worked with these Disposable objects but there is not a straight line what objects are MUST to dispose.
Have you read Kean´s article of that? That is the clearest article what I have seen.
http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
Cheers
Veli V.
I've written about this many times, and agree that the rules aren't simple.
For DBObjects, it depends on two things:
If the DBObject is database-resident, and you got it from a Transaction, you don't have to dispose it.
If the DBObject is not database-resident, or is database-resident and you got it from ObjectId.Open(), then you must dispose it.
Objects whose Dispose() methods have side-effects must always be disposed. Those include the Transaction and DocumentLock. Both of those do things when when they are disposed. You can often tell if an object will perform some specific side-effect in their finalizer, by examining its
AutoDelete property. When the value of this property is false, it usually means the object does nothing when its finalizer is called (either by the GC or by a call to Dispose()).
For example, when you get a Database from the Document's Database property, the AutoDelete property of the Database managed wrapper is false, because the drawing is open in the editor and for that reason its underlying AcDbDatabase must not be deleted. If on the other hand, you get a Database by calling the constructor (e.g., 'new Database(...)' ), and then you call ReadDwgFile(), the value of the AutoDelete property is true (and serves as the way of telling the Database managed wrapper that it must delete the wrapped AcDbDatabase).
For all DisposableWrappers, you must dispose them if code that runs from their Finalizer is not thread-safe, and could crash AutoCAD if it runs on the GC's thread. Unfortunately, that is not easy to determine, and perhaps is why Fenton gives the advice he does, but I still do not agree with it, or with the overall design which requires either guesswork, intimate knowledge of API internals, or taking no chances and grossly over-complicating client code by disposing *everything* as per my example above.
And here's something those Autodesk people didn't tell you:
Avoiding calls to Dispose() when it is unnecessary can actually improve the performance of AutoCAD and your plug-ins. The reason for that is because by default, the GC runs on a high-priority background thread, which means that on a multiple-processor system (do you know anyone that still runs AutoCAD on a single-processor system?), the GC can execute on a different (and presumably under-utilized) processor, concurrently, while AutoCAD and your plug-in run on another processor (e.g., a form of parallel execution). And, since AutoCAD doesn't leverage multiple processors, work done by the GC can be offloaded to another CPU core with virtually no performance impact on AutoCAD and your plug-in.
So, if you do follow the advice of Fenton and Stephen, the work that must be done by Dispose() will be done synchronously, requiring AutoCAD and your plug-in to
wait for it to complete, which is not the case if you just allow the GC to take care of it on another under-utilized CPU core.
Oh and BTW, does that also give a hint as to why disabling concurrent garbage collection in AutoCAD is a
really bad idea? If you do choose to do that, you should be the one sitting at that PC waiting the extra time and experiencing the lag in the UI during interactive operations like dragging. If you are going to do that for someone else only because it eliminates the crashes from the bugs in your code, do it only as a temporary stopgap measure, fix the bugs as soon as possible and re-enable concurrent garbage collection, as it should be.