È appropriato provare a controllare l'ordine di finalizzazione?

2

Sto scrivendo una classe che è approssimativamente analoga a un CancellationToken , tranne che ha un terzo stato per "non essere mai cancellato". Al momento sto cercando di decidere cosa fare se la 'fonte' del token è raccolta di dati inutili senza essere mai impostata.

Sembra che, in modo intuitivo, l'origine debba trasferire il token associato allo stato "mai annullato" quando sta per essere raccolto. Tuttavia, questo potrebbe attivare richiami che sono stati mantenuti in vita solo dal loro collegamento dal token. Ciò significa cosa potrebbero ora fare riferimento a questi callback nel processo di finalizzazione. Chiamarli sarebbe male.

Per "risolvere" questo problema, ho scritto questa classe:

public sealed class GCRoot {
    private static readonly GCRoot MainRoot = new GCRoot();
    private GCRoot _next;
    private GCRoot _prev;
    private object _value;
    private GCRoot() {
        this._next = this._prev = this;
    }
    private GCRoot(GCRoot prev, object value) {
        this._value = value;
        this._prev = prev;
        this._next = prev._next;
        _prev._next = this;
        _next._prev = this;
    }
    public static GCRoot Root(object value) {
        return new GCRoot(MainRoot, value);
    }
    public void Unroot() {
        lock (MainRoot) {
            _next._prev = _prev;
            _prev._next = _next;
            this._next = this._prev = this;
        }
    }
}

intendendo usarlo in questo modo:

Source() {
    ...
    _root = GCRoot.Root(callbacks);
}
void TransitionToNeverCancelled() {
    _root.Unlink();
    ...
}
~Source() {
    TransitionToNeverCancelled();
}

ma ora sono turbato. Questo sembra aprire la possibilità di perdite di memoria, senza in realtà risolvere tutti i casi di fonti nel limbo. Ad esempio, se una sorgente viene chiusa in uno dei suoi callback, viene rootata dalla radice di callback e quindi non può mai essere raccolta.

Presumibilmente dovrei lasciare che le mie fonti vengano raccolte senza sbirciare. O forse no? È mai opportuno provare a controllare l'ordine di finalizzazione o è un gigantesco segnale di pericolo?

    
posta Craig Gidney 04.12.2012 - 04:17
fonte

1 risposta

4

Is it appropriate to try to control the order of finalization?

No, non lo è. Che tu stia pensando ai finalizzatori è un gigantesco segnale di pericolo. Se è necessario smaltire risorse non gestite, utilizzare Dispose. Se si desidera il rilascio con scope di alcune risorse, riconsiderare; quindi usa Dispose se veramente ne trai beneficio.

Inoltre, sarei scettico riguardo alcune delle vostre preoccupazioni in merito al fatto che i callback siano in uno stato finalizzatore. Se puoi attivarli, le classi che chiamano non possono per definizione essere raccolte.

    
risposta data 04.12.2012 - 04:30
fonte

Leggi altre domande sui tag