risposta-alla-domanda-sullo-sviluppo-web-bd.com

Perché e come evitare perdite di memoria del gestore eventi?

Ho appena capito, leggendo alcune domande e risposte su StackOverflow, che l'aggiunta di gestori di eventi usando += in C # (o immagino, altri linguaggi .net) può causare perdite di memoria comuni ...

Ho usato molte volte gestori di eventi come questo in passato e non mi sono mai reso conto che possono causare o hanno causato perdite di memoria nelle mie applicazioni.

Come funziona (ovvero perché causa effettivamente una perdita di memoria)?
Come posso risolvere questo problema? Sta usando -= abbastanza per lo stesso gestore di eventi?
Esistono modelli di progettazione o best practice comuni per gestire situazioni come questa?
Esempio: come dovrei gestire un'applicazione che ha molti thread diversi, usando molti gestori di eventi diversi per generare diversi eventi sull'interfaccia utente?

Esistono modi validi e semplici per monitorarlo in modo efficiente in un'applicazione di grandi dimensioni già integrata?

149
gillyb

La causa è semplice da spiegare: mentre un gestore di eventi è sottoscritto, editore dell'evento contiene un riferimento a abbonato tramite il delegato del gestore di eventi (supponendo che il delegato sia un metodo di istanza).

Se l'editore vive più a lungo dell'abbonato, manterrà vivo l'abbonato anche quando non vi sono altri riferimenti all'abbonato.

Se annulli l'iscrizione all'evento con un gestore uguale, allora sì, ciò rimuoverà il gestore e l'eventuale perdita. Tuttavia, nella mia esperienza questo raramente in realtà è un problema, perché in genere trovo che l'editore e l'abbonato abbiano comunque una durata approssimativamente uguale.

è una possibile causa ... ma nella mia esperienza è piuttosto esagerato. Il tuo chilometraggio può variare, ovviamente ... devi solo stare attento.

185
Jon Skeet

Sì, -= è sufficiente, tuttavia, potrebbe essere abbastanza difficile tenere traccia di ogni evento assegnato, mai. (per i dettagli, vedi il post di Jon). Per quanto riguarda il modello di progettazione, dai un'occhiata a modello di eventi deboli .

12
Femaref

Un evento è in realtà un elenco collegato di gestori di eventi

Quando fai + = nuovo EventHandler sull'evento, non importa se questa particolare funzione è stata aggiunta come listener in precedenza, verrà aggiunta una volta per + =.

Quando l'evento viene generato, passa attraverso l'elenco collegato, elemento per elemento e chiama tutti i metodi (gestori di eventi) aggiunti a questo elenco, ecco perché i gestori di eventi vengono comunque chiamati anche quando le pagine non sono più in esecuzione finché sono vivi (radicati) e rimarranno vivi fintanto che saranno collegati. Quindi verranno chiamati fino a quando il gestore degli eventi viene sganciato con un - = nuovo EventHandler.

Vedi qui

e MSDN HERE

3
TalentTuner