2014-06-20 19 views
6

Ich entwickle schon seit einiger Zeit Bürolösungen in VBA und verfüge über relativ gute Kenntnisse in der Büroentwicklung in VBA. Ich habe beschlossen, dass es an der Zeit ist, etwas echtes Programmieren mit .Net zu lernen und einige Kinderkrankheiten zu haben.Kann ich etwas über ReleaseComObject erfahren? Kann ich es ignorieren?

Nachdem wir eine Reihe von Artikeln und Foren (hier und anderswo) durchgesehen haben, scheint es einige gemischte Informationen bezüglich der Speicherverwaltung in .Net bei der Verwendung von COM-Objekten zu geben.

Manche Leute sagen, ich sollte immer COM-Objekte deterministisch freigeben und andere sagen, ich sollte es fast nie tun.

Leute sagen, dass ich es tun sollte.

The book 'Professional Excel Development' auf Seite 861.

This stack exchange question hat, indem er „jede Bezugnahme Sie auf ein COM-Objekt machen muss freigegeben werden, wenn Sie nicht beantwortet tun , der Prozess wird im Speicher bleiben "

This blog schlägt vor, es zu benutzen löste seine Probleme.

sagen, Leute, die ich sollte es nicht tun:

This MSDN blog by Eric Carter Zustände „In VSTO Szenarien, müssen Sie in der Regel nicht immer ReleaseComObject nutzen.“

The book 'VSTO for Office 2007' die Co-Autor von Eric Carter scheint keine Erwähnung der Speicherverwaltung oder ReleaseComObject zu erwähnen.

This MSDN blog by Paul Harrington sagt, tun Sie es nicht.

Jemand mit gemischter Beratung:

Jake Ginnivan sagt, dass ich es immer Objekte auf COM tun soll, die die Methode Umfang nicht verlassen. Wenn ein COM-Objekt den Methodenbereich verlässt, dann vergessen Sie es. Warum kann ich die ganze Zeit nicht einfach vergessen?

Der Blog von Paul Harrington scheint darauf hinzudeuten, dass sich der Ratschlag von MS irgendwann in der Vergangenheit geändert hat. Ist der Aufruf von ReleaseCOMObject früher die beste Vorgehensweise, ist es aber nicht mehr? Kann ich die feineren Details der Speicherverwaltung MS überlassen und davon ausgehen, dass alles in Ordnung ist?

Antwort

1

Ich versuche, die folgende Regel in meiner Interop-Entwicklung bezüglich ReleaseComObject einzuhalten.

Wenn mein verwaltetes Objekt eine Art von Shutdown-Protokoll ähnlich wie IDisposable implementiert, rufe ich ReleaseComObject auf alle untergeordneten COM-Objekte, die ich Referenzen zu halten.Einige Beispiele für die Shutdown-Protokolle ich spreche:

  • IObjectWithSite.SetSite(null)
  • IOleObject.SetClientSite(null)
  • IOleObject.Close()
  • IDTExtensibility2.OnDisconnection
  • IDTExtensibility2.OnBeginShutdown

  • IDisposable.Dispose selbst

Dadurch können potenzielle zirkuläre Referenzen zwischen .NET- und nativen COM-Objekten beseitigt werden, sodass der verwaltete Garbage Collector seine Arbeit ungehindert erledigen kann.

Vielleicht gibt es etwas ähnliches, das in Ihrem VSTO-Interop-Szenario verwendet werden kann (AFAIR, IDTExtensibility2 ist dort relevant).

Wenn das Interop-Szenario beinhaltet IPC COM-Aufrufe (zum Beispiel, wenn Sie ein verwaltetes Ereignis-Senke-Objekt zu einem Out-of-proc COM-Server wie Excel übergeben), gibt es eine weitere Option, um das verwaltete Objekt externe Referenzen zu verfolgen: IExternalConnection interface. IExternalConnection::AddConnection/ReleaseConnection sind sehr ähnlich zu IUnknown::AddRef/Release, aber sie werden aufgerufen, wenn eine Referenz von einer anderen COM-Wohnung (einschließlich Wohnungen in separaten Prozessen) hinzugefügt wird.

IExternalConnection bietet eine Möglichkeit, einen fast universellen Shutdown-Mechanismus für Out-of-Proc-Szenarien zu implementieren. Wenn die Anzahl der externen Referenzen null erreicht, sollten Sie ReleaseComObject für alle externen Excel-Objekte aufrufen, auf denen Sie Referenzen haben, wodurch potenzielle zirkuläre COM-Referenzen zwischen Ihrem Prozess und dem Excel-Prozess effektiv aufgelöst werden. Vielleicht wurde so etwas bereits von VSTO Runtime implementiert (ich habe nicht viel Erfahrung mit VSTO).

Das heißt, wenn es keine klare Abschaltmechanismus gibt, rufe ich nicht ReleaseComObject. Außerdem verwende ich nie FinalReleaseComObject.

+1

Ein Experte für asynchronen Code und COM-Interop? Haben Sie Spaß daran, die schwierigsten Themen in C# zu finden, um zum Experten zu werden? ;) –

+0

@ScottChamberlain, weit davon entfernt ein Experte zu sein, ziemlich sicher angewandtes Wissen hier und da, aber danke für deine guten Worte :) – Noseratio

+0

Danke für deine Hilfe. Ich denke, das Endergebnis ist "es kommt darauf an". Ich denke, der einzige Weg, damit umzugehen, ist, über das Speichermanagement in COM vs .Net zu lernen. Ich war auf der Suche nach einem einfachen Ausweg, aber ich denke, es gibt keinen. –

0

Sie sollten es nicht ignorieren, wenn Sie mit der Office GUI arbeiten! Wie Ihre zweiten Link-Status:

Jeder Verweis auf ein COM-Objekt muss freigegeben werden. Wenn Sie dies nicht tun, bleibt der Prozess im Speicher.

Das bedeutet, dass Ihre Objekte im Speicher bleiben, wenn Sie sie nicht explizit freigeben. Da es sich um COM-Objekte handelt, ist der Garbage Collector für deren Freigabe verantwortlich. Excel und die anderen Tools sind jedoch ohne Kenntnisse des Garbage Collector in .NET implementiert. Sie beziehen sich auf die deterministische Freisetzung von Gedächtnis. Wenn Sie ein Objekt von Excel anfordern und es nicht ordnungsgemäß freigeben, kann es sein, dass Ihre Anwendung nicht ordnungsgemäß geschlossen wird, weil es so lange wartet, bis Ihre Ressourcen freigegeben werden. Wenn Ihre Objekte lange genug leben, um in gen1 oder gen2 zu gelangen, kann dies Stunden oder sogar Tage dauern!

Alle Überlegungen zum Freigeben von COM-Objekten beziehen sich auf Multithread-Szenarien oder Szenarien, in denen Sie gezwungen sind, viele Com-Objekte über mehrere Instanzen hinweg zu verschieben. Als guten Rat, erstellen Sie Ihre com-Objekte immer so spät wie möglich und veröffentlichen Sie sie so schnell wie möglich in der umgekehrten Reihenfolge als erstellt. Auch sollten Sie darüber nachdenken, Ihre Interop-Instanzen wo immer möglich privat zu halten.Dies reduziert die Möglichkeit, dass andere Threads oder Instanzen auf das Objekt zugreifen, während Sie es bereits freigegeben haben.

+0

Danke. In Bezug auf die Multithread-Szenarien, wenn OK-Objekte nicht freigegeben ist, dann muss es eine Möglichkeit geben, den Speicher wiederherzustellen. Ich verstehe nicht, warum dies nicht für Singlethread-Szenarien gilt. Auch der Typ, der buchstäblich das Buch über VSTO schrieb (Eric Carter wie oben verlinkt), sagt: "In VSTO-Szenarien müssen Sie ReleaseCOMObject normalerweise nicht verwenden". Ich denke, letztendlich bin ich nicht in der Lage, die Nuancen dieses Problems zu verstehen, bis ich viel mehr über das Speichermanagement im Allgemeinen lerne. –

+0

Office besteht aus nativen Anwendungen, in denen Sie selbst für die Zuweisung und Freigabe von Speicher sorgen müssen. COM stellt die Schnittstelle "IUnknown" bereit, die basierend auf Referenzzählern die automatische Speicherverwaltung unterstützt. Dies unterscheidet sich von .NET, wo der Garbage Collector nach "freisetzbaren" Objekten sucht. Beide Systeme sind nicht direkt kompatibel und deshalb sollten Sie selbst auf die Speicherverwaltung achten. Adam Nathan beschreibt auf diese Weise in seinem Buch ".NET und COM - Der vollständige Leitfaden zur Interoperabilität" auch Office-Interop-Szenarien. ;) – Carsten

Verwandte Themen