2009-09-01 5 views
5

J'ai un thread de travail dans mon application qui est responsable de trois choses différentes. Les demandes pour deux des travaux apparaissent dans les files d'attente que j'ai écrites, l'autre travail est activé lorsqu'une demande apparaît sur un flux réseau. Je voudrais que mon thread de travail attende quand il n'y a pas de travail à faire. C'est facile avec les deux files d'attente car elles exposent un ManualResetEvent qui est défini quand elles ont des éléments, cependant le NetworkStream ne semble pas avoir ceci. Le NetworkStream a été récupéré à partir d'un TcpClient.Comment attendre qu'un flux réseau ait des données à lire?

Ce que je suis après est le code qui ressemble à ceci:

while (notDone) 
{ 
    WaitHandle.WaitAny(new WaitHandle[] { queue1.HasData, queue2.HasData, netStream.HasData }); 
    // ... 
    if (netStream.DataAvailable) 
    { 
     netStream.Read(buffer, 0, 20); 
     // process buffer 
    } 
} 

Est-ce que quelqu'un connait un moyen d'obtenir un WaitHandle qui est définie lorsqu'un NetworkStream dispose de données?

Répondre

7

Vous pouvez utiliser les méthodes asynchrones de NetworkStream et définir un ManualResetEvent dans la méthode EndReceive.

// ... 
netStream.BeginRead(buffer, offset, callback, state); 
// ... 

dans la méthode de rappel

netStream.EndRead(ar); 
netStreamManualResetEvent.Set(); 

puis votre code

while (notDone) 
{ 
    WaitHandle.WaitAny(new WaitHandle[] { queue1.HasData, queue2.HasData, netStreamManualResetEvent}); 
    // ... 
    if (netStream.DataAvailable) 
    { 
     // make the buffer from the AsyncState in the callback method available here 
     // process buffer 
    } 
} 
+0

Est-il possible d'obtenir le BeginRead lire zéro octets? –

+0

Si l'hôte distant arrête la connexion et qu'il n'y a plus de données disponibles, 0 octet sera lu. Pourquoi demandez-vous? – SpaceghostAli

+0

Si vous ne pouvez pas faire en sorte que BeginRead lise zéro octet, vous devez commencer à gérer le tampon de lecture entre la boucle principale et le rappel. C'est totalement faisable mais n'est pas aussi bien que je le voudrais. –

2

La méthode la plus simple consiste probablement à utiliser un thread supplémentaire qui lit de manière synchrone et place des données supplémentaires dans une file d'attente supplémentaire.

Vous pouvez également utiliser des E/S asynchrones, mais c'est un peu délicat - et vous aurez toujours besoin d'une file d'attente supplémentaire.

Bien que Socket a une méthode Select() (et vous pouvez obtenir à une prise d'un NetworkStream) Je ne crois pas qu'il expose cette fonctionnalité d'une manière qui vous permet de le mélanger avec d'autres types de poignées d'attente.

Questions connexes