10
votes

Expressions Lambda, variables capturées et filetage

Je sais que .NET Lambda expressions peut capturer des variables extérieures. Cependant, je l'ai vu beaucoup de fois que les variables sont transmises explicitement à l'expression de Lambda en tant que paramètre et la bibliothèque .NET semble également supporter cela (par exemple, threadpool.Queueuerworkitem).

Ma question est que ce sont les limitations de ces captures? Qu'en est-il des lambdas qui sont réellement exécutés sur un fil différent de celui qu'ils ont été créés sur (par exemple, threadpool.QueuUserSerMorworkItem ou fil) ou des lambas qui agissent comme des rappels (c'est-à-dire invoqué ultérieurement)?

Généralement, quand devrais-je compter sur des variables capturées et quand utiliser des paramètres explicites? Par exemple: xxx

merci!

update : corrigé le deuxième exemple threadpool.QueueUserMeMItem. < / p>


0 commentaires

3 Réponses :


9
votes

Je pense dans votre premier exemple., vous voulez dire xxx

dans votre deuxième élément, où est le paramètre s vient? Je pense que vous voulez dire xxx

maintenant, ces deux travaillent tous deux de manière équivalente, mais

  • Dans le premier cas: le paramètre message est copié de la portée de Ce Dostuff méthode et stocké directement dans votre expression de Lambda lui-même, comme une fermeture. La Lambda a Garde une copie du message .

  • dans le second cas: message est envoyé à la queue et la file d'attente continue le tira (avec la Lambda), jusqu'à ce que la Lambda soit appelée. Il est passé au moment de la course à Lambda, à la Lambda.

    Je dirais que le second cas est plus flexible par programmation, car il pourrait vous permettre théoriquement de modifier ultérieurement la valeur du paramètre message avant que la Lambda soit appelée. Cependant, la première méthode est plus facile à lire et est plus à l'abri des effets secondaires. Mais dans la pratique, les deux travaillent.


1 commentaires

Vous avez raison, j'ai raté le paramètre dans la deuxième partie de l'exemple. Donc, si je comprends bien, dans la pratique, cela ne comporte pas vraiment lequel que j'utilise, mais que vous me recommanderiez d'aller avec des variables capturées, en raison de la simplicité (et de la lisibilité). Merci beaucoup pour votre réponse détaillée!



5
votes

Pour votre exemple (une référence à un objet de chaîne immuable), il ne fait aucune différence.

et en général, une copie d'une référence ne va pas faire beaucoup de différence. Il est important de travailler avec des types de valeur: xxx

La première version n'est pas du thread-coffre-fort, le deuxième et le troisième pourrait être.

La dernière version utilise le paramètre Etat d'objet une fonctionnalité FX2 (pré-linq).


2 commentaires

Je dois admettre que je trouve votre exemple de code déroutant. Dans la première partie, vous utilisez le paramètre, mais vous ne le transmettez pas pour faire la Lambda. Mais cela n'utilise pas une variable capturée (par ma compréhension), car cela signifierait directement l'utilisation de la variable de valeur. Votre deuxième exemple souligne la manière dont les types immuables se comportent, qui va bien, mais cela ne m'aidait pas à comprendre la différence. Pourriez-vous mettre à jour votre réponse pour clarifier cela?


Merci, c'est clair maintenant. La seule chose est que vous devriez également mettre à jour les commentaires dans le code. +1 Pour mentionner la threadsafety (bien que cela ne fonctionne que avec des types immuables), mais j'ai accepté la réponse de Sanjay Manohar, car elle était plus rapide, claire et détaillée. Merci aussi pour votre aide!



2
votes
  1. Si vous voulez que les foncteurs anonymes font référence au même état, capturez un identifiant du contexte commun.
  2. Si vous voulez que les Lambdas apatrides (comme je le recommanderais dans une application simultanée) utilisent des copies locales.

0 commentaires