"In order to open the ObjectId ForRead, you're presumably using a Database Transaction... You mention Using blocks, but did you ever Commit() the Transaction?"
So, you are suggesting that it is necessary to commit a transaction even when objects are only opened ForRead? And this could account for the memory consumption? I do not currently commit when I do not write to the drawing database. When I began this project, all of the example code I encountered utilized transactions (and not even StartOpenCloseTransaction, but StartTransaction). I have since learned that it is possible to open objectIDs for read or write without the use of a transaction. Either avoiding a transaction on using StartOpenCloseTransaction are both much more performant (as an aside).
"Also, I'm sure your app makes sense to you, but it sounds like your logic of reading the Object's properties at SelectionChanged is premature (unless some modeless dialog is dynamically updated?)... Selection is a primary function, so unless you're then acting on a Click event (ContextMenu for example), or Command, you're inviting an abundance of effort upon your app, IMO. "
When I began work on this plugin, I knew very little about AutoCAD and its APIs. Two years or so later I probably still don't know much about either subject. As I explained, I had to replace the Properties window in AutoCAD (specifically its functionality for editing dynamic block properties). I found an approach that worked, which is to subscribe to ImpliedSelectionChanged. In the handler method, I first determine if the selected block is a part of my application. I should note that there is a button which can be used to disable this integration. The replacement block property editor should only be active when the user intends to edit block properties. Anyway, likely there is a better way to implement this functionality. I only described the workings of this part of the plugin to provide an idea of what might be causing the memory consumption.
Posting code.... there are tens of thousands of lines of code which directly call AutoCAD's .net API, and much more code which drives these calls or does... many other things. I cannot zero in on a specific bit of code which is causing the issue.
In any case I am grateful for your reply and any further advice you might have (especially about the question of the need to call Commit when only reading from the database).
I made the same post to the AutoDesk forums (
http://forums.autodesk.com/t5/net/net-plugin-causes-high-memory-consumption-leak-not-in-managed/td-p/5633915). This was the only reply I received so far (the responder is a person I have come to respect. He is very knowledgeable.)
"I have no idea on how the native code wrapped by .NET API handle memory, but one thing surely results in more memory user: manipulating BlockReference's DynamicBlockReferenceProperties, especially when the dynamic block is quite complicated, because whenever a dynamic propery is set to a different value, AutoCAD creats a new anonymous block definition so that the instance of the blockreference with that specific dynamic property value can have a block definition to reference to. After using your app to manipulate the complicated dynamic blocks for a while, if you go to "Purge" dialog box, you would see tons of purge-able anonymous blocks, which surely take up momeries. It is known side effect that using many dynamic blocks with many dynamic properties slows AutoCAD down noticeably."
He is correct that many purgeable anonymous blocks are created. I automatically purge the BlockTable before each save because of this problem, which otherwise eventually causes drawing files to become very large. There is also an option to purge the BlockTable at regular intervals in my application. However, even running the purge command and doing a 'purge all' on the drawing barely dents the amount of memory consumed. I also tried combining purge all and having UNDO completely disabled from the time a drawing is first created. To no avail.