die richtige Technik zum Freigeben eines Socket / Ereignis / unzulässigen Codes mit dem Dispose / Finalize-Muster

8

Wie man das Dispose-Muster implementiert, wenn meine Klasse einen Socket & amp; Ereignis?

Sollte es so sein?

%Vor%

Ich bin verwirrt ... ist Socket-Klasse "verwalteter Code c # Version von WinSock"? also sollte es freigegeben werden, wenn der Benutzer dispose ("isDisposing IS true") anruft Was ist mit Eventhandlern?

also bei finalisierten Kommentar Abschnitt sollte nur Inptr Objekte frei? Danke.

    
roman 13.11.2012, 07:26
quelle

4 Antworten

3

Ich denke, es gibt viele Möglichkeiten, mit wegwerfbaren Objekten umzugehen, egal ob sie Ereignisse haben oder nicht.

Ist nur eine wilde Vermutung, aber wenn Sie eine Klasse aus dem .net-Framework genommen haben und diese Klasse eine Dispose () -Methode hat, können Sie ziemlich sicher sagen, dass es sich um verwalteten Code handelt, so dass Sie nur das Dispose aufrufen können Methode, anstatt den Destruktor selbst zu erstellen. Dies ist ziemlich veraltet, da Sie, wie Sie in meinem Beispiel sehen, die IDisposable-Schnittstelle auch in Ihren eigenen Klassen implementieren und dann Ihre internen Objekte ordnungsgemäß entsorgen können.

Könnte das für Sie hilfreich sein?

%Vor%     
Jorge Alvarado 13.11.2012 07:43
quelle
2

Da Socket eine verwaltete Klasse ist, die Richtlinien für die Implementierung von IDisposable gibt an, dass kein Finalizer benötigt wird. Ein Finalizer führt tatsächlich dazu, dass die Garbage Collection des Objekts verzögert wird, da er den Finalizer während der ersten Garbage Collection aufruft und das Garbage Collection Objekt bei der zweiten Garbage Collection erneut aufruft.

In Bezug auf das Ereignis möchten Sie sich wahrscheinlich von dem Ereignis in der Methode Dispose abmelden, da die Ereignissubskription bewirkt, dass innerClass einen Verweis auf die Instanz von MyClass enthält, es sei denn, das innerClass-Objekt ist kurzlebig. Weitere Informationen zu Ereignissen und zu Dispose finden Sie diese Frage .

Ich denke, dass die folgende Implementierung für Ihr Szenario ausreichen würde:

%Vor%

Der Teil in Ihrem Code, den Sie mit "finalisierten nicht gemanagten Code hier" kommentiert haben, sollte nur nicht verwaltete Ressourcen freigeben, z. B. Handles in Form von IntPtr usw. Seit der Einführung von SafeHandle in .NET 2.0 müssen Sie dies selten tun, da Sie Ihre% co_de einpacken können % in IntPtr und behandle sie dann als verwaltete Ressource.

    
PHeiberg 13.11.2012 10:28
quelle
1

Du sollst niemals etwas unwidersprochen lassen.

Nach meiner Erfahrung ist der weit verbreitete "soft error" Dispose(disposing) Mechanismus schlecht durchdacht. Ich bevorzuge "hard error" .

Wenn ich Objekte schreibe, die Dispose() implementieren, dehne ich normalerweise eine Klasse MyDisposable aus, die #if DEBUG wie folgt ausführt:

  1. Sein Konstruktor erfasst den aktuellen Stack-Trace und speichert ihn für später. (Hinweis: Dies ist extrem langsam, Microsoft weiß nur warum.)
  2. Die Klasse enthält ein bool disposed -Member, das mit false initialisiert wurde.
  3. Dispose() bestätigt, dass das Objekt nicht bereits entfernt wurde und markiert das Objekt dann als disposed.
  4. Der Destruktor des Objekts (der bei der Finalisierung aufgerufen wird) prüft, ob das Objekt entsorgt wurde. Wenn nicht, wird der Stack-Trace ausgegeben, der während der Erstellung aufgezeichnet wurde. Dadurch kann ich die genaue Stelle in meinem Quellcode finden, die ein Einwegobjekt zugewiesen hat, aber vergessen hat, es zu entsorgen.

Auch Objekte, die von MyDisposable normalerweise abgeleitet werden, setzen !disposed als Vorbedingung in jeder einzelnen Methode, sogar in jedem einzelnen Getter, voraus.

Das obige garantiert, dass:

  1. Es gibt nur eine Möglichkeit, wie ein Objekt entsorgt werden kann.
  2. Jedes verfügbare Objekt wird nur einmal entsorgt.
  3. Sobald das Objekt entfernt wurde, wird keine Methode eines wegwerfbaren Objekts mehr aufgerufen.
  4. Wenn ich jemals vergessen habe, ein Einwegobjekt zu entsorgen, werde ich es herausfinden, und ich werde genau wissen, wo es zugewiesen wurde.

Es versteht sich von selbst, dass, wenn nicht #DEBUG , dann MyDisposable zu praktisch nichts kompiliert wird, um die Leistung nicht zu behindern.

Folglich versuche ich (wenn möglich) Klassen zu vermeiden, die den "soft error" Dispose(disposing) -Mechanismus implementieren, ohne sie zuerst in Klassen zu implementieren, die meinen "harten Fehler" implementieren. em> Dispose() Mechanismus.

    
Mike Nakis 17.02.2015 09:52
quelle
0

Die vorhandenen Antworten sagen es bereits, aber sie sind ziemlich ausführlich. Lassen Sie mich klarer sagen, dass dies alles ist, was Sie brauchen:

%Vor%

Dies ist nicht abgekürzt. Sie können alles andere löschen.

Keine Notwendigkeit für einen Finalizer. Keine Notwendigkeit für Null-Tests. Sie können mehrere Male sicher entsorgen.

Das "displace pattern" existiert für finalisierbare Objekte (extrem selten) und für Vererbung (selten). Fast immer hilft dieses Muster überhaupt nicht, sondern beeinträchtigt die Codequalität.

    
usr 17.02.2015 10:16
quelle