C #: Benachrichtigung vor der Erfassung von WeakReference?

8

Gibt es in C # /. NET eine Möglichkeit, eine Benachrichtigung zu erhalten, bevor das Objekt, auf das eine schwache Referenz verweist, zerstört wird? Grundsätzlich möchte ich erlauben, dass ein Objekt gesammelt wird, aber mache etwas, bevor das Objekt zerstört wird, ohne Code zu ändern, um Destruktoren hinzuzufügen (da ich nicht genau wissen werde, welche Arten von Objekten mit meinem Code verklagt werden).

Danke, Robert

    
Robert Fraser 17.07.2009, 20:29
quelle

6 Antworten

5

Das kannst du nicht tun. Sie können jedoch beobachten, wenn sich ein GC nähert (es gibt neue GC APIs in CLR v3.5Sp1, die Ihnen dies ermöglichen, GCNotifications)

    
mfawzymkh 18.07.2009, 00:36
quelle
6

Nein, es gibt keine Möglichkeit, diese Funktionalität zu erreichen.

Nach ein paar Spekulationen glaube ich nicht, dass es möglich ist, ein Feature so zu implementieren, wie Sie es beschreiben.

Beachten Sie, dass an dem Punkt, an dem das Objekt, das von einer WeakReference gehalten wird, gesammelt wird, es keine Referenzen mehr gibt (daher ist es sammelbar). Damit ein Ereignis für Sie nützlich ist, muss das Objekt als Teil des Ereignisses bereitgestellt werden. Dies bedeutet, dass die Referenz von sammelbar zu nicht sammelbar gegangen ist. Es gibt nichts, was den Handhabungscode daran hindert, eine Referenz auf dieses Objekt zurückzunehmen. Daher kann das Objekt nicht mehr als sammelbar angesehen werden. Die CLR müsste das Objekt erneut durchlaufen, um erneut sicherzustellen, dass es sammelbar ist.

Sie können sehen, wie das zweite Mal in der Umgebung des Ereignisses nicht ausgelöst werden konnte, da dies zu nicht einfangbaren Objekten führen würde.

Es wäre ein Missbrauch der Namensgebung zu behaupten, dass dieses Ereignis ausgelöst wurde, kurz bevor ein Objekt gesammelt wurde. Einfach deshalb, weil jeder Handler verhindern könnte, dass dies gesammelt wird, indem eine neue Referenz auf das Objekt erstellt wird. Stattdessen müsste es "ObjectMaybeAboutToBeCollected" sein. Dies wird Ihnen wahrscheinlich nicht das Verhalten geben, nach dem Sie suchen.

    
JaredPar 17.07.2009 20:31
quelle
6

.Net 4.0 hat die Lösung, die Sie brauchen: ConditionalWeakTable . Hier ist ein kurzes Programm, das die Idee demonstriert. (besprochen hier auch )

%Vor%     
Reuven Bass 04.06.2012 10:59
quelle
0

Ihre Frage ergibt für mich keinen Sinn. Wo soll der Code liegen, der genannt wird? Vorausgesetzt, dass die schwachen Referenzen vor der Zerstörung des referenzierten Objekts auf Null gesetzt werden, ist es nicht sinnvoll, dass es Teil der Klasse ist, die auf das zu zerstörende Objekt verweist. Und es gibt bereits Code in dem referenzierten Objekt, das aufgerufen wird, bevor das Objekt zerstört wird - das ist der Destruktor.

Was ist das eigentliche Designproblem, das Sie lösen möchten? Es könnte einen besseren Weg geben.

    
Mark Bessey 17.07.2009 20:58
quelle
0

Für das, was Sie beschreiben, wäre Finalizer eine bessere Möglichkeit.

    
tdh 04.08.2009 04:03
quelle
0

Es wäre möglich, eine Semantik zu haben, die Ihrer Beschreibung ähnlich ist, wenn eine schwache Referenz mit einem Notifier ähnlich wie ein Objekt mit einem Finalizer betrachtet wurde, das heißt, wenn das Objekt für niemanden mehr interessant war würde es für die Fertigstellung und Benachrichtigung in die Warteschlange gestellt werden; Der Eintrag in der Warteschlange würde als eine Live-Referenz betrachtet werden, so dass das Objekt erst gesammelt wird, wenn es ausgeführt wurde.

Da dies nicht möglich ist, könnte der beste mögliche Ansatz wahrscheinlich darin bestehen, dass alle Referenzen "Ich bin an diesem Objekt interessiert" auf ein leichtes Wrapper-Objekt zeigen, das wiederum auf das reale Objekt zeigen würde. schwache "Referenzen" verweisen auf einen anderen Wrapper, der auch auf das reale Objekt zeigen würde. Der erste Wrapper sollte einen Verweis auf den zweiten enthalten, aber nicht umgekehrt. Der erste Wrapper sollte einen Finalizer haben, der geeigneten Code auslöst, wenn er den Gültigkeitsbereich verlässt.

Leider habe ich keine vollständigen Implementierungen einer solchen Strategie gesehen. Es gibt einige wichtige Einschränkungen zu beachten. Unter ihnen: (1) Finalizer sollten nie auf Sperren warten, noch irgendetwas tun, das eine Ausnahme werfen könnte; (2) Code, der auf andere Objekte zugreift, die möglicherweise nicht mehr in den Geltungsbereich fallen, muss auf die Möglichkeit vorbereitet sein, dass sie bereits fertiggestellt sind, gerade finalisiert werden, auf die Fertigstellung warten oder noch andere Referenzen haben; (3) Wenn ein Finalizer einen verwurzelten Verweis auf ein finalisierbares Objekt speichert, das als für die Garbage Collection geeignet befunden wurde, kann ein solches Objekt finalisiert werden, obwohl die Live-Referenz existiert.

    
supercat 17.11.2010 23:55
quelle