Frage

Ich habe eine Menge von Artikeln im Netz über die Freigabe RCW ist sicher zu lesen, und es scheint mir, dass niemand genau zustimmen kann, was Ordnung in, was getan werden muss, so frage ich euch für eure Meinungen. Zum Beispiel könnte man dies tun:

object target = null;
try {
    // Instantiate and use the target object.
    // Assume we know what we are doing: the contents of this try block
    // do in fact represent the entire desired lifetime of the COM object,
    // and we are releasing all RCWs in reverse order of acquisition.
} finally {
    if(target != null) {
        Marshal.FinalReleaseComObject(target);
        target = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

Allerdings befürworten tun einige Leute die Garbage Collection vor Marshal.FinalReleaseComObject, einige nach, und einige nicht. Ist es wirklich notwendig, manuell jedes einzelne RCW GC, vor allem, nachdem sie bereits von ihrem COM-Objekt gelöst wurde?

Meiner Meinung nach, wäre es einfacher und leichter sein, nur das RCW aus dem COM-Objekt zu lösen und den RCW verläßt natürlich ablaufen:

object target = null;
try {
    // Same content as above.
} finally {
    if(target != null) {
        Marshal.FinalReleaseComObject(target);
    }
}

Ist es ausreichend, das zu tun?

War es hilfreich?

Lösung

Ihr Verweis auf das Ziel COM-Objekt zu haben, freigegeben wird, ist es ausreichend, und bevorzugt , um nur Marshal.FinalReleaseComObject anrufen und nicht zwingen, einen Collect. Mit anderen Worten, Sie haben in Ihrer Verantwortung zu lösen Ihre Referenz so schnell erfüllt, wie Sie mit ihm fertig waren. Ich werde nicht die Frage der FinalReleaseComObject vs ReleaseComObject berühren.

Dies lässt die größere Frage, warum tun Menschen GC.Collect() und WaitForPendingFinalizers() befürworten nennen?

Da für einige Designs, ist es schwer zu wissen, wann es nicht mehr geschafft, Referenzen, so dass Sie nicht sicher ReleaseComObject aufrufen können. Sie haben zwei Möglichkeiten, lassen Sie den Speicher aufbauen und hoffen, dass ein collect passiert oder ein R-erzwingen. [Steven Jansen nach unten Abstimmung Hinweis in den Kommentaren sehen]

Ein weiterer Hinweis ist, dass target zu null Einstellung in der Regel nicht erforderlich ist, und speziell ist unnötig in Ihrem Beispielcode. Objekte zu nichts Einstellung ist üblich, für VB6 Praxis, da sie einen Referenzzähler auf Basis Garbage Collector verwendet. Der Compiler für C # ist klug genug, um (wenn für die Freigabe Gebäude) zu wissen, dass target nach seiner letzten Verwendung nicht erreichbar ist und GC'd werden könnte, noch bevor Umfang zu verlassen. Und letzten Einsatz, ich meine letzte mögliche Verwendung so gibt es Fälle, in denen Sie setzen könnte es null. Sie können dies unter dem Code selbst sehen:

   using System;
   class GCTest
   {
       ~GCTest() { Console.WriteLine("Finalized"); } 
       static void Main()
       {
           Console.WriteLine("hello");
           GCTest x = new GCTest();
           GC.Collect();
           GC.WaitForPendingFinalizers();
           Console.WriteLine("bye");
       }
   }

Wenn Sie Release bauen (zum Beispiel CSC GCTest.cs), „Abgeschlossen“ wird ausgedruckt zwischen „Hallo“ und „Auf Wiedersehen“. Wenn Sie Debug bauen (zum Beispiel CSC / debug GCTest.cs), "Abgeschlossen" wird nach "bye" auszudrucken während x Einstellung vor null würde Collect() "fixed" haben, dass.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top