8
votes

Différence entre NetworkStream.Read () et NetworkStream.beginread ()?

J'ai besoin de lire à partir de Networkstream qui enverrait des données au hasard et la taille des paquets de données conserve également la variation. Je mettant en place une application multi-threadée dans laquelle chaque thread aurait son propre flux à lire. S'il n'y a pas de données sur le flux, l'application doit continuer à attendre que les données arrivent. Toutefois, si le serveur est effectué l'envoi de données et a terminé la session, il devrait alors quitter.

Au départ, j'avais utilisé la méthode pour obtenir les données du flux, mais elle utilisait le fil et maintenues à attendre jusqu'à ce que les données soient apparues sur le flux.

La documentation sur MSDN suggère,

Si aucune donnée n'est disponible pour la lecture, la méthode de lecture renvoie 0. Si le L'hôte distant arrête la connexion, et toutes les données disponibles ont été reçu, la méthode de lecture complète immédiatement et retourner zéro octets.

Mais dans mon cas, je n'ai jamais reçu la méthode pour renvoyer 0 et quitter gracieusement. Il attend juste indéfiniment.

Dans mon autre enquête, je suis tombé sur beginread qui regarde le flux et invoque une méthode de rappel asynchrone, dès qu'il reçoit les données. J'ai essayé de rechercher diverses implémentations en utilisant également cette approche, cependant, je n'ai pas pu identifier lorsqu'il utiliserait beginread être bénéfique par opposition à lu .

Comme je le regarde, beginread n'a que l'avantage d'avoir l'appel ASYNC, qui ne bloquerait pas le fil actuel. Mais dans ma candidature, j'ai déjà un fil séparé pour lire et traiter les données du flux, de sorte que cela ne ferait pas beaucoup de différence pour moi.

  • Quelqu'un peut-il m'aider s'il vous plaît comprendre le mécanisme d'attente et de sortie pour beginread et comment est-il différent de lis ?

  • Quelle serait la meilleure façon de mettre en œuvre la fonctionnalité souhaitée?


2 commentaires

Êtes-vous sûr que le côté distant ferme correctement la connexion? Je n'ai jamais eu de problème avec lue ne pas retourner. Votre approche semble avoir la bonne direction.


@Matthew bien, honnêtement, je ne peux pas dire ça à coup sûr. C'est un service tiers que nous lisons. Ils ont spécifié les horaires d'arrêt et nous supposons que cela se produit comme mentionné. Je veux juste vérifier et revérifier à ma fin d'abord avant de l'élever un drapeau.


4 Réponses :


12
votes

J'utilise begayread , mais continuez à bloquer le fil à l'aide d'un waihandle : xxx

essentiellement, il permet un délai d'attente des lectures ASYNC Utilisation du waihandle et vous donne une valeur booléenne ( complété ) si la lecture était terminée dans l'heure définie ( 2000 dans ce cas). < / p>

Voici mon code de lecture complet de flux copié et collé de l'un de mes projets mobiles Windows: xxx


3 commentaires

Merci @generictyTypea, cela ressemble à une approche intéressante, mais il ne me convient aucun moyen de déterminer une période d'expiration correcte. Néanmoins, je pense que cela peut être modifié un peu pour obtenir une résolution à mon problème. J'essayerais et j'essayais, s'il réussit. BTW, votre poignée m'a été souriant .. :)


Si je ne me trompe pas, vous devez toujours appeler Endabc sur chaque appel Beverabc. Dans le code ci-dessus, s'il y a un délai d'attente, la fin n'est jamais appelée. Un rappel qui appelle fin (et gère toutes les exceptions possibles) devrait probablement être ajouté au code ci-dessus.


@Speksetc - Je pense que vous vous trompez. J'appelle toujours une fin: INT BYTESREAD = StreamPread (Asyncreader);, mais peut-être que je devrais changer le code pour appeler ce code directement après la ligne BOOL complétée = HANDINE.WAITONE (2000, FAUX); afin d'éliminer la duplication.



5
votes

ASYNC E / S peut être utilisé pour obtenir la même quantité d'E / S dans moins de threads.

Comme vous le souhaitez, votre application a un fil par flux. Ceci est correct avec un petit nombre de connexions, mais si vous avez besoin de prendre en charge 10000 à la fois? Avec ASYNC E / S, cela n'est plus nécessaire car le rappel d'achèvement de lecture permet de transmettre le contexte d'identifier le flux correspondant. Vos lectures ne bloquent plus, vous n'avez donc pas besoin d'un fil par flux.

Si vous utilisez Sync ou ASYNC E / S, il existe un moyen de détecter et de gérer le courant de courant sur les codes de retour d'API pertinents. begayread devrait échouer avec IoException si le la prise a déjà été fermée. Un refermé pendant que votre ASYNC lue est en attente, vous pourrez déclencher un rappel, et endread vous dira ensuite l'état de jeu.

Lorsque votre candidature appelle beyread, Le système attendra jusqu'à ce que les données soient reçu ou une erreur se produit, puis Le système utilisera un fil séparé exécuter le rappel spécifié méthode et blocs sur endread jusqu'à Le réseau de réseaux fournis lit les données ou jette une exception.


1 commentaires

Merci tsteve. Le thread par flux est due à beaucoup d'autres considérations de conception et n'est pas vraiment un problème. Nous aurions 10 fils simultanés au maximum.



0
votes

BeginRead est un processus asynchronisé qui signifie que votre fil principal commencera à exécuter une lecture dans un autre processus. Alors maintenant, nous avons 2 processus parallèles. Si vous voulez obtenir le résultat, vous devez appeler Endread, qui donne le résultat.

Certains pseudo xxx

mais si votre fil principal n'a rien sinon à faire et vous devez avoir besoin du résultat, vous devez appeler lire.


2 commentaires

L'implication que plusieurs processus sont impliqués ici est totalement faux.


@ Steve, je pense que @ bonshington signifie "fil", quand il a dit "processus".



0
votes

Avez-vous essayé serveur.receIpeTimeout? Vous pouvez définir l'heure à laquelle lire () Functon attendra les données incommodées avant de retourner zéro. Dans votre cas, cette propriété est probablement définie sur infinie quelque part.


0 commentaires