Disposal of Revit API Objects

KR raised a very valid and

important


question

in the discussion of

exporting parameters to Excel
:

Question: It would be great if you could clarify in broad terms when to dispose of Revit API objects.

You underline the importance of

disposing of Transaction objects
.

Many objects in the Revit API implement IDisposable, for example FilteredElementCollector, DB.Document, etc.

If I create a new FilteredElementCollector within the confines of Revit API, e.g. in an external command, Idling event handler, external event etc., do I still have to dispose of this object?

The rule of thumb in the .NET world is: ‘Always dispose of all objects implementing IDisposable that you instantiated’.

Answer by Arnošt Löbel: You are absolutely correct – it is advisable to explicitly dispose every disposable object, either by calling its Dispose method, deleting it (in C++), or scoping it in a ‘using’ block.
However, it is not absolutely necessary in the managed environment, and there should normally be no harm if you do not do so.
The Garbage Collector (GC, for short) will collect the abandoned objects and everything should be just fine, memory-wise.

It might be a little problematic to depend only on the GC if there is ‘something’ that must be done by the object destructor or finaliser, and that ‘something’ is timely essential, meaning it should happen is some semi-predetermined time rather than randomly when the GC is triggered.
That is why, in my opinion, it is generally recommended to explicitly dispose of all disposable objects.
Again, it is not over-important for all objects; I would not bother with filtered element collectors, for example.

Transactions (and T-Groups, S-Transaction, Edit Modes, etc.), are different.
While it is no more (nor less) important to dispose of them explicitly and in a timely fashion, it is imperative that they are properly ‘finished’.
The ‘finishing’ may mean something different to each of these objects; for example – it might be either Committing or Rolling Back for transactions.
This ‘finishing’ is in fact the part that ‘must’ be done soon enough, most importantly before the API client (external command, event, etc.) terminates.
Since the ‘finishing’ procedure is automatically invoked from the object destructor, the disposing action indirectly ‘finishes’ the object as well.
This is the reason why it is important to scope transactions in a ‘using’ block; because ‘using’ does not let the object leave the scope without disposing (and finishing) it, even in the case of exceptions.

Let me repeat this in yet other words: if your application can guarantee that Commit or RollBack is always called for all transactions that have been Started, it is not necessary to dispose the transaction objects, either explicitly (dispose, delete) or implicitly (using).
However, the nice thing about ‘using’ blocks is that they automatically guarantee this.


Comments

4 responses to “Disposal of Revit API Objects”

  1. Thanks for following up on it Jeremey

  2. Dear KR,
    My pleasure entirely. Thank you for raising the issue.
    Cheers, Jeremy.

  3. David Tan Avatar
    David Tan

    Hi Jeremy,
    I seemingly encountered a memory issue a couple of weeks ago. I tried to create a set of view sheets most of which were inserted a raster image. After about 25+ view sheets created, I found my Windows is close to running out of memory (93% of physical memory usage), while CPU usage was fine.I noticed that the memory usage increasing along with view sheet creation one by one.
    Here’s my code to insert raster image to view sheet:
    protected Element InsertImage(string imageFile)
    {
    ImageImportOptions options = new ImageImportOptions();
    options.Placement = BoxPlacement.Center;
    options.RefPoint = new XYZ(0, 0, 0);//图片的初始化位置为图片的几何中心在原点。
    Element elemImage = null;
    using (Transaction trans = new Transaction(RevitDoc))
    {
    trans.Start(“Insert Image”);
    if (!(RevitDoc.Import(imageFile, options, ViewSheet, out elemImage)))
    {
    string message = string.Format(“错误!!!向视图导入图片“{0}””, imageFile);
    throw new InvalidOperationException(message);
    }
    trans.Commit();
    }
    return elemImage;
    }
    I tried to dispose the raster image element after insertion but it didn’t work. Is that possible that Revit doesn’t handle raster image element properly? Could you please give me some hints? Thanks a lot!
    Best Regards,
    David Tan

  4. David Tan Avatar
    David Tan

    I forgot to mention that all images inserted to the view sheets were actually exported from Revit project and family. The size of these image files are from 500KB to 1.5MB, which I don’t think is large.

Leave a Reply to Jeremy TammikCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading