Was ist heute der richtige Weg, um mit COM-Objekten zu arbeiten?

8

Dies ist eine sehr häufige Frage, und ich habe mich entschieden, sie zu stellen, weil diese Frage heute eine andere Antwort haben kann. Hoffentlich helfen die Antworten, zu verstehen, wie man mit COM-Objekten richtig arbeitet. Persönlich fühle ich mich sehr verwirrt, nachdem ich unterschiedliche Meinungen zu diesem Thema bekommen habe.

In den letzten 5 Jahren habe ich mit COM-Objekten gearbeitet und die Regeln waren sehr klar für mich:

  1. Verwenden Sie eine einzelne Periode in Codezeilen. Wenn Sie mehr als einen Zeitraum verwenden, erstellen Sie temporäre Objekte hinter der Szene, die nicht explizit freigegeben werden können.
  2. Verwenden Sie foreach nicht, verwenden Sie stattdessen eine for-Schleife und geben Sie jedes Element bei jeder Iteration frei
  3. Rufen Sie nicht FInalReleaseComObject auf, verwenden Sie stattdessen ReleaseComObject.
  4. Verwenden Sie GC nicht zum Freigeben von COM-Objekten. GC Intent dient hauptsächlich zum Debuggen der Verwendung.
  5. Geben Sie Objekte in umgekehrter Reihenfolge ihrer Erstellung frei.

Einige von euch könnten frustriert sein nach dem Lesen dieser letzten Zeilen, das ist was ich wusste, wie ich Com Object richtig erstellen / veröffentlichen kann, ich hoffe, dass ich Antworten bekomme, die es klarer und unbestritten machen.

Nachfolgend finden Sie einige Links, die ich zu diesem Thema gefunden habe. Einige von ihnen sagen, dass es ReleaseComObject aufrufen muss und einige von ihnen nicht.

  

"... In VSTO-Szenarios müssen Sie ReleaseCOMObject normalerweise nicht verwenden. ..."

  

"... Sie sollten diese Methode verwenden, um das zugrunde liegende COM-Objekt zu befreien, das Referenzen enthält ..."

UPDATE:

Diese Frage wurde als zu breit markiert. Wie gewünscht, werde ich versuchen, einfachere Fragen zu vereinfachen und zu stellen.

  1. Ist ReleaseComObject erforderlich, wenn Sie mit COM-Objekten arbeiten oder GC aufruft?
  2. Ändert VSTO die Art und Weise, wie wir mit COM-Objekten gearbeitet haben?
  3. Welche der obigen Regeln habe ich geschrieben und welche sind falsch? Gibt es noch andere?
ehh 19.06.2016, 06:13
quelle

1 Antwort

10

Das .NET / COM-Interop ist gut entworfen und funktioniert korrekt. Insbesondere verfolgt der .NET Garbage Collector COM-Verweise korrekt und gibt COM-Objekte ordnungsgemäß frei, wenn sie keine verbleibenden Laufzeitverweise mehr haben. Das Interferenzieren mit den Referenzzählungen des COM-Objekts durch Aufrufen von Marshal.ReleaseComObject(...) oder Marshal.FinalReleaseComObject(...) ist ein gefährliches, aber häufiges Anti-Pattern. Leider kamen einige der schlechten Ratschläge von Microsoft.

Ihr .NET-Code kann korrekt mit COM interagieren, während Sie alle fünf Ihrer Regeln ignorieren. Wenn Sie eine deterministische Bereinigung von COM-Objekten auslösen müssen, die nicht mehr von der Laufzeit referenziert werden, können Sie einen GC sicher erzwingen (und möglicherweise warten, bis die Finalizer abgeschlossen sind). Ansonsten müssen Sie in Ihrem Code nichts Besonderes tun, um mit COM-Objekten umzugehen.

Es gibt einen wichtigen Vorbehalt, der zur Verwirrung über die Rolle des Müllsammlers beigetragen haben könnte. Beim Debuggen von .NET-Code wird die Lebensdauer von lokalen Variablen künstlich bis zum Ende der Methode verlängert, um das Beobachten der Variablen unter dem Debugger zu unterstützen. Das bedeutet, dass Sie Verweise auf ein COM-Objekt (und daher wird der GC nicht bereinigen) immer noch später verwaltet haben als das erwartete Formular, wenn Sie nur auf den Code schauen. Eine gute Problemumgehung für dieses Problem (das nur unter dem Debugger auftritt) besteht darin, den Bereich von COM-Aufrufen von den Bereinigung GC-Aufrufen aufzuteilen.

Als Beispiel hier ist ein C # -Code, der mit Excel interagiert und richtig bereinigt. Sie können in eine Konsolenanwendung einfügen (fügen Sie einfach einen Verweis auf Microsoft.Office.Interop.Excel hinzu):

%Vor%

Sie werden sehen, dass der Excel-Prozess ordnungsgemäß heruntergefahren wird, um anzuzeigen, dass alle COM-Objekte ordnungsgemäß bereinigt wurden.

VSTO ändert keines dieser Probleme - es ist nur eine .NET-Bibliothek, die das native Office-COM-Objektmodell umschließt und erweitert.

Es gibt eine Menge falscher Informationen und Verwirrung über dieses Problem, einschließlich vieler Posts auf MSDN und StackOverflow.

Was mich schließlich überzeugt hat, genauer hinzusehen und den richtigen Rat zu finden, war dieser Beitrag Ссылка zusammen mit dem Finden des Problems mit Referenzen, die unter dem Debugger auf einer StackOverflow-Antwort lebendig gehalten werden.

Eine Ausnahme zu dieser allgemeinen Anleitung ist, wenn das COM-Objektmodell erfordert, dass Schnittstellen in einer bestimmten Reihenfolge freigegeben werden. Der hier beschriebene GC-Ansatz gibt Ihnen keine Kontrolle über die Reihenfolge, in der die COM-Objekte vom GC freigegeben werden.

Ich habe keinen Hinweis darauf, ob dies gegen den COM-Vertrag verstoßen würde. Im Allgemeinen würde ich erwarten, dass COM-Hierarchien interne Referenzen verwenden, um sicherzustellen, dass alle Abhängigkeiten von der Sequenz ordnungsgemäß verwaltet werden. Z.B. Im Fall von Excel würde man erwarten, dass ein Range-Objekt einen internen Verweis auf das übergeordnete Worksheet-Objekt behält, so dass ein Benutzer des Objektmodells beide nicht explizit am Leben erhalten muss.

Es kann Fälle geben, in denen selbst Office-Anwendungen empfindlich auf die Reihenfolge reagieren, in der COM-Objekte freigegeben werden. Ein Fall scheint zu sein, wenn die OLE-Einbettung verwendet wird - siehe Ссылка

Es wäre also möglich, ein COM-Objektmodell zu erstellen, das fehlschlägt, wenn Objekte in der falschen Reihenfolge freigegeben werden, und das Interop mit einem solchen COM-Modell würde dann etwas mehr Sorgfalt erfordern und manuelle Eingriffe in die Referenzen erfordern / p>

Aber für allgemeine Interop mit den Office-COM-Objektmodellen stimme ich mit dem VS Blogpost " Marshal.ReleaseComObject - ein Problem getarnt als Lösung ".

    
Govert 03.07.2016, 13:50
quelle

Tags und Links