2013-05-07 13 views

Répondre

5

Le moyen sûr est de prendre une copie du gestionnaire et augmenter au lieu-à-dire

var handler = ActionDataReceived; 
if (handler != null) 
{ 
    handler(this, new ActionEventArgs(logMessage)); 
} 

Cette volonté atténuer les conditions de concurrence qui pourraient mener à l'annulation de l'événement avant que vous ne tentiez de le déclencher.


Comme @EricLippert a souligné cette ne couvre pas le scénario dans lequel l'état interne du gestionnaire est modifié après la cession a eu lieu.

+1

Je vous assure que cela n'atténue ** pas ** les conditions de course; cela ne fait qu'atténuer la condition de concurrence dans laquelle l'événement est remplacé par null après vérification de la nullité. Par exemple, supposons que nous ayons la course suivante entre les threads Alpha et Bravo: Alpha copie le délégué dans le gestionnaire et le vérifie pour la nullité. Ensuite, Bravo supprime la méthode M de la liste des gestionnaires d'événements et * détruit l'état que M doit fonctionner correctement * en supposant à tort que M ne sera plus jamais appelé parce qu'il n'est plus un gestionnaire. Alors Alpha invoque M, qui explose. –

+0

Ce modèle n'atténue pas cette course du tout; Si tel est le cas, vous devez trouver un autre moyen d'atténuer la course. Généralement, la meilleure chose à faire est: si ça fait mal quand vous faites cela, ne faites pas cela. Un gestionnaire dans un programme multithread doit être * toujours * dans un état où il peut être appelé en toute sécurité *, qu'il soit ou non actuellement enregistré en tant que gestionnaire. –

+0

@EricLippert Par * toute * condition de course je faisais référence à tout type de scénario où l'événement pourrait être désaffecté/changé. Cependant, d'après ce que vous dites, le gestionnaire peut encore être changé? J'avais cru comprendre qu'une fois que vous auriez pris une copie du gestionnaire, elle serait exécutée telle quelle (peu importe si elle est modifiée par la suite avant d'invoquer). – James

Questions connexes