2013-02-13 4 views
8

diesen Code vor:Wie das Ziel eines schwachen Verweis auf eine sichere Art und Weise zu bekommen

var weakRef = new WeakReference(new StringBuilder("Mehran")); 
if (weakRef.IsAlive) 
{ 
    // Garbage Collection might happen. 
    Console.WriteLine((weakRef.Target as StringBuilder).ToString()); 
} 

Es ist möglich, für GC.Collect nach weakRef.IsAlive Prüfung ausgeführt und vor dem weakRef.Target verwenden.

Bin ich falsch damit? Wenn es möglich ist, gibt es einen sicheren Weg, das zu tun? B. eine API wie weakRef.GetTargetIfIsAlive() wäre angemessen.

+1

Überprüfen Sie http://msdn.microsoft.com/en-gb/library/ms404247.aspx –

+1

Sie sollten zuerst zu einer starken Referenz und dann nach "null". Sie können sicher sein, dass Ihre starke Referenz nicht null ist. –

Antwort

12

Diese API existiert bereits; weakRef.Target gibt null zurück, wenn das Objekt bereits bereinigt wurde.

StringBuilder sb = weakRef.Target as StringBuilder; 
if (sb != null) 
{ 
    Console.WriteLine(sb.ToString()); 
} 
1

Nehmen Sie eine lokale Kopie des Ziels und überprüfen Sie auf Null.

WeakReference.Target kehrt null, wenn das Ziel gesammelt wurde, aber du bist Sorge ist, dass es zwischen Ihrem .IsAlive Scheck und bekommen das Ziel gesammelt wird.

var weakRef = new WeakReference(new StringBuilder("Mehran")); 

if (weakRef.IsAlive) 
{ 
    var stringBuilder = weakRef.Target as StringBuilder; 

    if (stringBuilder != null) 
    { 
     Console.WriteLine(stringBuilder.ToString()); 
    } 
} 

Console.WriteLine((weakRef.Target as StringBuilder).ToString()); wird eine Null-Referenz Ausnahme auslösen, wenn die Umwandlung fehlschlägt.

+0

Ich habe mich gefragt, warum die Überprüfung von 'weakRef.IsAlive' erforderlich ist, @supercat hat die Frage beantwortet, daher denke ich, dass es nicht notwendig ist, sie zu überprüfen. – mehrandvd

+1

@Mehrandvd Es könnte nicht notwendig sein, ich habe es nur in diesem Beispiel verwendet, da es auf Ihrer ursprünglichen Frage basiert. Es kann nicht schaden, es zu benutzen, aber ja, es ist möglicherweise eine sinnlose Überprüfung angesichts der 'as' Cast und Null-Check auf' .Target'. –

+1

@TrevorPilley: Verwenden von 'IsAlive' auf einer' WeakReference', wenn ein 'true' Wert bedeuten würde, dass man das Ziel abrufen will, ist sinnlos. Es ist möglich, dass bei einigen Speicherbereinigern 'if (wr1.IsAlive && wr2.IsAlive && wr3.IsAlive) {Foo wt1 = wr1.Target als Foo, wt2 = wr2.Target als Foo, wt3 = wr3.Target als Foo; if (wr1! = null && wr2! = null && wr3! = null) {... benutze alle drei Dinge ...} 'könnte hilfreich sein, wenn z.B. ein gleichzeitiger Garbage-Collector, der nachverfolgen konnte, ob seit dem letzten GC ein Verweis auf etwas erstellt wurde. Auf einem solchen GC, wenn wr3 gestorben wäre, aber wr1 und wr2 noch lebten ... – supercat

9

Die Eigenschaft IsAlive existiert nicht zugunsten des Codes, der das Ziel verwenden möchte, wenn es lebendig ist, sondern eher für den Code, der herausfinden möchte, ob das Ziel gestorben ist, aber nicht interessiert wäre in jedem Fall darauf zugreifen. Wenn der Code Target gegen null testen würde, würde Target vorübergehend einen stark verwurzelten Verweis enthalten (der Code, der gegen null testet), und es ist möglich, dass das Erzeugen eines solchen verwurzelten Verweises das Objekt davon abhält, den Müll zu sammeln wenn es sonst wäre. Wenn der Code nicht an Target interessiert ist, außer um herauszufinden, ob der Code noch ungültig ist, gibt es keinen Grund dafür, dass Code die Referenz erhält. Es kann einfach IsAlive stattdessen testen und geeignete Maßnahmen ergreifen, wenn es false zurückgibt.

+0

Ich habe mich gefragt, warum 'IsAlive' existiert. Das ist eine sehr schlaue Antwort, Danke. – mehrandvd

+1

@Mehrandvd: Es ist nicht schwer, sich eine konkurrierende GC vorzustellen, bei der das Abrufen des 'Target' aus einer' WeakReference' verhindern würde, dass dieses Objekt im nächsten Zyklus * gesammelt wird, selbst wenn die Referenz sofort verworfen wurde *.Auf einem solchen System könnte Code, der etwas unternehmen wollte, sobald ein Objekt nicht mehr benötigt wurde und "Target" anstelle von "IsAlive" verwendet wurde, das betreffende Objekt für immer am Leben erhalten. – supercat

Verwandte Themen