Question

Je lisais une page sur les événements sur MSDN, et Je suis tombé sur un extrait d’exemple de code qui me laisse perplexe.

Le code en question est le suivant:

// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

Je comprends les intentions du code, mais je ne vois pas en quoi cette ligne crée une copie de quoi que ce soit. Il ne fait que copier la référence ; ce n'est pas réellement une copie complète de l'instance de délégué. Donc, dans ce but, cela n’empêche en aucun cas la situation de concurrence critique.

Me manque-t-il quelque chose d'évident ici?

Était-ce utile?

La solution

Les délégués étant immuables, la référence obtenue dans ce code est garantie de ne pas changer. Si un utilisateur s'abonne ou se désabonne après la vérification de la valeur NULL, un nouveau délégué est créé et défini pour l'événement. Cependant, puisque vous avez une référence à un objet complètement différent et l'invoquez, vous n'avez pas à vous soucier de sa nullité.

Autres conseils

Vous avez raison; c'est copier la référence.

Cependant, les délégués sont immuables; Lorsque vous ajoutez un gestionnaire à un événement, un nouveau délégué est créé. Il associe le ou les gestionnaires actuels au nouveau, puis est affecté au champ.

L'instance de délégué référencée par le champ ne peut pas être modifiée, elle évite donc la condition de concurrence critique.

Eric Lippert a déjà couvert cela dans un post .

Cela provient également de MSDN.

"La liste d'invocation d'un délégué est un ensemble ordonné de délégués dans lequel chaque élément de la liste appelle exactement l'une des méthodes représentées par le délégué. Une liste d'invocation peut contenir des méthodes en double. Au cours d'une invocation, les méthodes sont appelées dans l'ordre dans lequel elles apparaissent dans la liste d'appels. Un délégué tente d'appeler chaque méthode dans sa liste d'appels. les doublons sont invoqués une fois pour chaque fois qu'ils apparaissent dans la liste d'appels. Les délégués sont immuables; une fois créée, la liste des appels d'un délégué ne change pas. "

if (que ce soit! = null) any (); donne l'impression que quel que soit ne soit jamais nul lorsque any () est appelé , mais cela ne garantit pas cela dans un scénario basé sur des threads. Un autre thread peut définir any = null entre la vérification et l'appel.

Foo temp = whatever;
if (temp != null) temp();

Ce code supprime la possibilité du déréférencement NULL, car temp est un fichier local et ne sera donc jamais modifié par un autre thread. Donc, cela empêche une condition de concurrence. Cela n'empêche cependant pas toutes les conditions de course pertinentes. Eric Lippert a fait un discussion plus élaborée sur d’autres problèmes liés au code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top