Table of Contents

Object lifetimes

VTK counts references and frees an object when the last one goes. A C# proxy holds one; Dispose drops it at once, the finalizer once the garbage collector finds the proxy unreachable.

One reference per proxy One reference per proxy
var points = new vtkPoints(); // New(): 1 reference, the proxy's
using var polyData = new vtkPolyData();
polyData.SetPoints(points);       // 2: the poly data's too
var again = polyData.GetPoints(); // 3: a returned object, another proxy, another reference

// Dispose drops the proxy's reference at once; the object goes when no one holds it
again.Dispose();  // 2
points.Dispose(); // 1: the poly data's

GetReferenceCount() counts VTK's own references too: a new vtkSphereSource reports 2.

using (var reader = new vtkXMLUnstructuredGridReader())
{
  // ... read, take what's needed
}

// or for the rest of the block
using var grid = new vtkUnstructuredGrid();

What VTK keeps

What VTK holds stays alive, whatever happens to its proxies:

// VTK counts its own references: the actor holds the mapper after its proxy is gone
using var actor = new vtkActor();
using (var mapper = new vtkPolyDataMapper())
{
  actor.SetMapper(mapper);
}

using var held = actor.GetMapper(); // a new proxy for the same mapper

The same goes for a filter's input and output, a renderer's actors, and an observer VTK holds, a C# vtkCommand included (Observers and messages). A proxy isn't the object: GetMapper() twice gives two proxies, each with a reference; NativePointer tells whether they're the same object.

When to dispose

The garbage collector sees only the small proxy, not the native memory behind it.

Dispose promptly Why
render windows, renderers, mappers, actors, textures they release OpenGL resources, which needs the thread that renders
large data sets and arrays the memory goes only with the last reference
readers and filters each holds its output
small objects no need: the finalizer is fine

Threads

The finalizer releases on its own thread, where no OpenGL context is current: fine for data, not for rendering objects. Dispose those on the thread that renders, or set VtkFinalizer.Context to its SynchronizationContext: the finalizer then posts the releases there (Rendering and hosting). Dispose releases on the calling thread. A release posted to a context whose thread has ended doesn't happen.