Pattern degli eventi, problemi comuni (memory leak)
Individuate e risolvete i problemi comuni degli eventi: annullate la sottoscrizione per evitare memory leak, conservate i riferimenti ai delegate per rimuoverli e usate un pattern di sottoscrizione con IDisposable.
Pattern degli eventi, problemi comuni (memory leak) è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 3 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 3 lezioni in totale.
Panoramica sulle insidie
Obiettivo: utilizzare gli eventi in modo sicuro.
- Annulli la sottoscrizione per prevenire le perdite di memoria
- Conservi un riferimento allo stesso gestore per poterlo rimuovere
- Preferisca un piccolo pattern IDisposable per la pulizia
- Eviti gestori anonimi inline che non può scollegare
Annullare la sottoscrizione per evitare perdite
Gli eventi conservano riferimenti ai sottoscrittori. Se il produttore vive a lungo e non si scollega mai il sottoscrittore, quest'ultimo non può essere raccolto dal garbage collector.
using System;
public class Publisher
{
public event EventHandler Tick;
public void Fire()
{
EventHandler h = Tick;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Subscriber
{
public void Handle(object s, EventArgs e)
{
Console.WriteLine("Handling tick");
}
public void Subscribe(Publisher p) { p.Tick += Handle; }
public void Unsubscribe(Publisher p) { p.Tick -= Handle; } // required to avoid leaks
}
public class Program
{
public static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber();
s.Subscribe(p);
p.Fire(); // prints once
s.Unsubscribe(p); // detach when done
s = null; // now eligible for GC in a real app
p.Fire(); // no output
}
}
Conservare il riferimento al gestore
Per scollegare un gestore anonimo, lo memorizzi in una variabile e passi la stessa istanza a -=.
using System;
public class Button
{
public event EventHandler Click;
public void Simulate()
{
EventHandler h = Click;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Button b = new Button();
// BAD: cannot easily remove this later
// b.Click += (s, e) => Console.WriteLine("inline");
// GOOD: store the handler, attach, later detach the same instance
EventHandler saved = (s, e) => Console.WriteLine("saved");
b.Click += saved;
b.Simulate(); // prints "saved"
b.Click -= saved; // can remove because we kept the reference
b.Simulate(); // no output
}
}
Sottoscrizione disposable
Restituisca un IDisposable da Subscribe. Utilizzi using per annullare automaticamente la sottoscrizione.
using System;
public class Ticker
{
public event EventHandler Tick;
public IDisposable Subscribe(EventHandler handler)
{
Tick += handler;
return new Unsubscriber(this, handler);
}
private sealed class Unsubscriber : IDisposable
{
private Ticker _t;
private EventHandler _h;
private bool _done;
public Unsubscriber(Ticker t, EventHandler h) { _t = t; _h = h; }
public void Dispose()
{
if (!_done)
{
_t.Tick -= _h;
_done = true;
}
}
}
public void Fire()
{
EventHandler h = Tick;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Ticker t = new Ticker();
using (t.Subscribe((s, e) => Console.WriteLine("tick")))
{
t.Fire(); // prints once
}
t.Fire(); // nothing after disposal
}
}
Scollegare con try/finally
Utilizzi try/finally quando un gestore deve essere scollegato anche se viene generata un'eccezione.
using System;
public class Alarm
{
public event EventHandler Ring;
public void Trigger()
{
EventHandler h = Ring;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Alarm a = new Alarm();
EventHandler h = (s, e) => Console.WriteLine("ring");
a.Ring += h;
try
{
a.Trigger(); // do work with subscription active
}
finally
{
a.Ring -= h; // always detach
}
a.Trigger(); // no output
}
}
Suggerimenti per evitare perdite
Suggerimenti:
- I sottoscrittori dovrebbero gestire l'annullamento della propria sottoscrizione (Dispose, finally o un metodo esplicito).
- Eviti di effettuare sottoscrizioni con gestori anonimi inline che non può rimuovere.
- Presti attenzione agli eventi statici: spesso sopravvivono agli oggetti.
- Mantenga brevi i gestori; non blocchi il produttore.
Causa delle perdite con gli eventi
Riepilogo
Riepilogo: annulli la sottoscrizione per prevenire le perdite, conservi i riferimenti ai gestori per poterli rimuovere e preferisca pattern di pulizia basati su disposable o finally per gestire in sicurezza il ciclo di vita degli eventi.
Domande Frequenti
La lezione «Pattern degli eventi, problemi comuni (memory leak)» è gratuita?
Sì — il testo completo di «Pattern degli eventi, problemi comuni (memory leak)» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 3 lezioni in totale.
Cosa imparerò in «Pattern degli eventi, problemi comuni (memory leak)»?
Individuate e risolvete i problemi comuni degli eventi: annullate la sottoscrizione per evitare memory leak, conservate i riferimenti ai delegate per rimuoverli e usate un pattern di sottoscrizione c… Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare C# Academy?
Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 3.
Quanto tempo richiede la lezione «Pattern degli eventi, problemi comuni (memory leak)»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione C# Academy?
Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- delegate, Action/Func, closure
- Eventi: pubblicazione/sottoscrizione, parola chiave event
- Pattern degli eventi, problemi comuni (memory leak)