2015-10-05 8 views
8

Diciamo che ho questo (incompleta) di classe, in cui alzo un evento senza prima di assegnarlo a una variabile per renderlo thread-safe:È sempre sicuro annullare l'iscrizione a un evento all'interno del gestore?

public class Test 
{ 
    public event EventHandler SomeEvent; 

    void OnSomeEvent(EventArgs e) 
    { 
     if (SomeEvent != null) 
      SomeEvent(this, e); 
    } 
} 

sarebbe sicuro per annullare la sottoscrizione di un gestore di eventi da stesso, o potrebbe esserci qualche problema simile a ciò che accadrebbe quando si rimuovono gli articoli da una raccolta mentre lo si enumera?

void SomeEventHandler(object sender, EventArgs e) 
{ 
    testInstance.SomeEvent -= SomeEventHandler; 
} 
+0

cos'è un 'testinstance'? – Tigran

+1

Presumibilmente è la stessa istanza di 'Test' come' sender'. – BoltClock

+1

@Tigran Come ha detto BoltClock, è lo stesso di '(Test) sender' – Trisibo

risposta

5

Per chiarire l'altra risposta un po ':

eventi sono basate su delegati (in quasi tutti i casi). I delegati sono immutabili. Questo vale anche per i delegati multicast.

Quando si richiama un evento, il delegato viene caricato e quindi richiamato. Se il campo in cui è archiviato il delegato viene modificato, ciò non influisce sul delegato già caricato.

È quindi possibile modificare l'evento dal gestore. Quelle modifiche non influiranno sul richiamo attualmente in esecuzione. Questo è garantito.

Tutto ciò si applica solo agli eventi supportati da un delegato. C# e CLR supportano eventi personalizzati che potrebbero fare qualsiasi cosa.

+0

Sì, avrei sicuramente dovuto iniziare: i delegati sono immutabili e questa è la chiave! +1 –

4

sarebbe sicuro, però, è sufficiente sapere che non è una garanzia che il codice in SomeEventHandler verrà eseguito solo una volta. Potrebbe verificarsi una condizione di competizione se si dispone di codice multithread.

Modifica: L'annullamento dell'iscrizione da un evento consentirà, dietro le quinte, di combinare i delegati per produrre un elenco di delegati. (È possibile trovare molti dettagli su that article by Jon Skeet the man himself)

Si noti che l'evento utilizza i blocchi per garantire la sicurezza del thread sulla combinazione Delegato. Una volta associato un delegato al tuo evento, avrai un elenco risultante di delegati. Quando si alza un evento, tuttavia, ciò che è non garantito è che verrà utilizzata l'ultima versione dei delegati combinati. (vedi eventi thread-safe) ma questo non è correlato al fatto che l'evento è stato sganciato dall'interno dell'evento.

spero la mia modifica fornisce abbastanza chiarimento :)

+0

Inoltre, di solito mi disconnetto dall'evento prima di sottoscriverlo. Solo per verificare che SomeEventHandler venga eseguito solo una volta. – tier1

+1

Potete fornire qualche prova o citazione sul motivo per cui questo è sicuro? –

+0

Assolutamente. Ho appena modificato la risposta. Spero che questo ti aiuti. –

Problemi correlati