2010-09-09 4 views
3

Pourquoi les méthodes de socket de rappel asynchrone sont-elles généralement statiques? (supposons que je comprenne la classe statique, la méthode et les objets de données). Y aurait-il une erreur de conception/logique fondamentale si l'on devait écrire une classe en utilisant ces méthodes comme des instances? Y at-il quelque chose de spécial que l'on devrait prendre soin d'éviter?Pourquoi les méthodes de socket de rappel asynchrone sont-elles généralement statiques?

+0

Qu'est-ce qui vous fait croire que les méthodes de socket de rappel asynchrone sont généralement statiques? – dtb

+0

Peut-être (j'espère dans mon cas :-)) Je me trompe, mais une recherche rapide sur Google semble démontrer qu'au moins la plupart des exemples de code semblent être statiques. – Jess

+0

@Jess: Un lien (ou douze) serait utile. Je suis avec @dtb. –

Répondre

3

Il n'y a pas de raison particulière pour qu'ils soient statiques. Tout dépend de votre conception.

Si le rappel doit accéder aux membres de la classe, il peut être déclaré en tant que membre d'instance. Cependant, vous devrez vous assurer que vous synchronisez correctement l'accès aux membres de l'instance car le rappel peut être appelé simultanément à partir de différents threads.

Je suppose que les exemples que vous avez examinés ont tous transmis les données requises au rappel via le IAsyncResult.AsyncState et n'ont donc pas nécessité d'informations supplémentaires de la classe. Si vous pouvez faire cela, il peut simplifier votre code, puisque vous ne devez plus vous soucier de fil, etc .. syncronization

Mise à jour

Juste pour préciser, sur la base des observations, il semble que je devrais avoir plus beed explicite. Ce n'est pas que le callback statique serait thread-safe, mais plutôt que dans une conception où les données requises sont passées au callback et bien sûr ces données ne sont pas partagées par d'autres threads alors le verrouillage n'est pas nécessaire. Et puisque le callback est passé toutes les données qu'il requiert, il n'a pas besoin d'accéder à l'instance de classe et peut donc être rendu statique.

+3

L'accès aux membres statiques à partir d'autres threads n'a rien d'intrinsèquement sûr. La même synchronisation devrait avoir lieu. –

+0

@Adam, j'aurais dû être plus clair. J'essayais de dire que lorsque les données sont transmises au rappel et que le rappel n'a pas besoin d'accéder aux données partagées, aucun verrouillage n'est requis. Lors de l'accès aux données de la classe. –

+0

Peut-être mon manque d'expérience en C++ est-il visible, mais en C# il n'y aurait aucune raison de croire qu'une fonction statique n'accéderait pas à des ressources statiques partagées. –

1

Les fonctions de rappel sont généralement statiques car vous ne savez rien de la classe sur laquelle vous effectuez un rappel. En fait, une fonction d'instance de classe porte généralement le pointeur "this" en tant que premier paramètre caché.

Voir: http://www.drdobbs.com/184403375;jsessionid=P5JGJLQBDYGWBQE1GHOSKH4ATMY32JVN?pgno=2

Edit: Voir aussi Why callback functions needs to be static when declared in class

+1

Notez que ceci est vrai seulement pour C++, pas C#. –

1

au moins en C++, une méthode non statique devrait recevoir this comme un paramètre caché. Puisque tout ce qui l'appelle comme rappel ne le sait pas, il ne passera pas ce paramètre supplémentaire. Si vous parvenez à appeler une fonction membre non statique en tant que rappel, tout ce qui tenterait d'utiliser des données de membre (ce qui arriverait via this) aurait (presque certainement) des problèmes majeurs.

Je suppose que C# est au moins quelque peu similaire, même si je n'ai pas étudié suffisamment les détails pour être sûr. Indépendamment de la langue, le code doit savoir avec quelles données travailler. La différence évidente est que C# prend également en charge les délégués, qui sont extrêmement utiles pour les rappels.

Editer: pour éviter cela, au moins en C++ c'est assez simple. Vous souhaitez généralement utiliser une bibliothèque comme ACE, Boost ASIO ou POCO qui vous protège de la plupart des détails désordonnés. Si vous en regardez autour, vous en trouverez probablement au moins quelques dizaines d'autres. Oh, je devrais ajouter que la plupart des bibliothèques de style de cadre d'application (par exemple, wxWidgets et Qt) incluent des classes pour vous protéger de la plupart des détails désordonnés. La différence évidente est que ceux-ci ont tendance à «prendre en charge» la conception de l'application en général (bien que, en toute justice, je devrais ajouter que ACE tend un peu vers la même chose).

Bien sûr, les gens ont aussi écrit des bibliothèques pour C#, mais je n'en ai pas assez utilisé pour faire une recommandation significative à leur sujet. Beaucoup dépend également du niveau d'abstraction que vous recherchez. WCF (par exemple) fait un peu plus que simplement vous protéger des détails désordonnés. Plutôt, il construit essentiellement sa propre idée complète de la façon de travailler avec les réseaux, qui arrive à (quelque part là-dedans) être en mesure d'utiliser des sockets - mais pour la plupart, vous n'êtes plus vraiment travailler avec des sockets, vous travaillons avec WCF, qui utilise des sockets. En fin de compte, cependant, la bibliothèque cache, ne change pas, ce qui se passe réellement. Quelque part dans la bibliothèque, Winsock effectue un rappel à une fonction membre statique ou à une fonction libre qui utilise la convention d'appel C de base attendue. Cette fonction utilise ensuite des données supplémentaires (généralement le paramètre qui lui est passé) pour déterminer les éléments à invoquer à partir de là. Ce qui varie, c'est l'épaisseur d'une couche d'isolation entre votre code et le callback de Winsock.

+0

Vous parlez ici de callbacks C. C++ est différent, vous devez passer un pointeur vers la méthode qui sera invoquée sur une instance de classe. Si la bibliothèque ne le fournit pas, ce rappel doit être exposé à l'utilisateur en tant que foncteur ou interface (observateur, par exemple). Sinon c'est une très mauvaise bibliothèque minimaliste de style C qui est difficile à utiliser et vous finirez par écrire beaucoup de code ou au moins envelopper les rappels avec quelque chose de plus utile. –

+0

@Vlad: avez-vous pris la peine de lire la question? Il ne demande pas si c'est la seule façon de faire les choses, mais demander * pourquoi * le code qu'il a vu est écrit de cette façon. Oui, il existe des bibliothèques qui vous protègent, mais elles fonctionnent généralement comme il le décrit: appelez une fonction membre statique (ou une fonction gratuite), qui utilise d'autres données pour invoquer ce que vous avez demandé. –

+2

délégués C# (les pointeurs de fonction, fondamentalement, bien que légèrement plus que cela) ne souffrent pas de la même limitation. Les délégués qui pointent vers des méthodes d'instance sont syntaxiquement identiques aux délégués qui pointent vers des méthodes statiques. Que le délégué reste entièrement dans le code managé ou soit marshalé en code non managé, le runtime .NET (CLR) gère la distinction instance-vs-static de manière transparente. –

Questions connexes