Domanda

Sto usando diversi comportamenti fondono e trigger su un controllo Silverlight. Mi chiedo se non v'è alcun meccanismo per il distacco automatico o quella che OnDetaching () viene chiamato per un comportamento o grilletto quando non viene più utilizzato il controllo (cioè rimosso dall'albero visivo).

Il mio problema è che c'è una perdita di memoria gestita con il controllo a causa di uno dei comportamenti. I sottoscrive comportamento di un evento su qualche oggetto longevo nel l'override OnAttached () e devono essere cancellarsi dalla quell'evento nel OnDetaching () hanno la priorità in modo che possa diventare un candidato per la raccolta dei rifiuti. Tuttavia, OnDetaching () non sembra essere sempre chiamato quando rimuovo il controllo dalla struttura ad albero visuale ... l'unico modo per ottenere che accada è staccando esplicitamente i comportamenti problematici prima di rimuovere il controllo e allora è correttamente garbage collection .

In questo momento la mia unica soluzione era quella di creare un metodo pubblico nel code-behind per il controllo che può passare attraverso e staccare eventuali comportamenti noti che potrebbero causare problemi di raccolta dei rifiuti. Spetterebbe al codice client di sapere di chiamare questo prima di rimuovere il controllo dal pannello. Non mi piace molto questo approccio, quindi sto cercando un modo automatico di fare questo che mi sto sottovalutando o un suggerimento migliore.

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
È stato utile?

Soluzione

Quello che si ha realmente bisogno in questo caso non è un modo per staccare automaticamente, ma per garantire che il riferimento di cui all'oggetto vissuto a lungo non osserva il comportamento (e quindi tutto il resto ha un riferimento a) di essere garbage collection.

Questo è acheived implementando un modello di mediatore. Il concetto è che non si danno l'oggetto longevo un delegato con un riferimento al vostro Behaviour, invece si crea una classe mediatore come un go-between. Gli addetti mediatore per l'evento oggetti a lungo vissuto e ha conseguito un WeakReference al comportamento. Quando l'oggetto a lungo vissuto genera l'evento i controlli mediatore che il WeakReference è ancora vivo, se è così chiama un metodo su di esso per trasmettere l'evento. Se quando si verifica l'evento i reperti mediatore che il WeakReference non è più vivo spicca il suo gestore di eventi dall'oggetto lunga durata.

Quindi non v'è nulla che impedisca il comportamento e tutto il resto coinvolti venga garbage raccolti tutti i thats sinistra è un piccolo esempio mediatore con riferimento morto ancora attaccato all'oggetto longeva. Dal momento che questi mediatori sono piccole che non rappresentano un problema reale e anche quelli spariranno la prossima volta che viene generato l'evento.

Per fortuna non c'è bisogno di costruire questa roba da soli altri hanno già fatto. Si chiama WeakEventListener. Questo blog: Evidenziando un "contributo debole"; Miglioramenti rendono prevenire le perdite di memoria con WeakEventListener ancora più facile! ha un ottimo insieme di link sull'argomento.

Altri suggerimenti

Joost van Schaik offre un'alternativa modo per ripulire i riferimenti da comportamenti collegati, evitando il problema con la perdita di memoria. Dipende da fare il lavoro di pulizia con i delegati degli eventi caricati e scaricati del AssociatedObject.

Egli offre anche un codice-frammento di per la generazione di stub per comportamenti collegati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top