2009-09-01 8 views
5

Mam wątek pracownika w mojej aplikacji, który jest odpowiedzialny za trzy różne rzeczy. Żądania dwóch zadań pojawiają się w kolejkach, które napisałem, drugie zadanie jest aktywowane, gdy żądanie pojawia się w strumieniu sieci. Chciałbym, aby moja wątek roboczy czekał, kiedy nie ma pracy do wykonania. Jest to łatwe w przypadku dwóch kolejek, ponieważ eksponują one ManualResetEvent, który jest ustawiony, gdy mają elementy, jednak wydaje się, że NetworkStream nie ma tego. Obiekt NetworkStream został pobrany z TcpClient.Jak czekasz, aż strumień sieciowy odczyta dane?

Co Jestem po to kod, który wygląda mniej więcej tak:

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

Czy ktoś zna sposób, aby uzyskać WaitHandle który jest ustawiony, gdy NetworkStream ma danych?

Odpowiedz

7

Można użyć metod asynchronicznych w NetworkStream i ustawić ManualResetEvent w metodzie EndReceive.

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

wewnątrz metody wywołania zwrotnego

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

następnie kod

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

Czy to możliwe, aby uzyskać BeginRead czytać bajtów zerowych? –

+0

Jeśli zdalny host zamknie połączenie, a nie ma już dostępnych danych, zostanie odczytanych 0 bajtów. Dlaczego pytasz? – SpaceghostAli

+0

Jeśli nie możesz ustawić BeginRead na zero bajtów, musisz zacząć zarządzać buforem odczytu między główną pętlą a oddzwonieniem. Jest to całkowicie wykonalne, ale nie jest tak ładne, jak bym chciał. –

2

Najprostszym sposobem jest prawdopodobnie użycie dodatkowego wątku, który czyta synchronicznie i umieszcza dodatkowe dane w dodatkowej kolejce.

Alternatywnie można użyć asynchronicznego IO, ale to trochę kłopotliwe - i nadal potrzebna jest dodatkowa kolejka.

Chociaż Socket ma metodę Select() (i można dostać w gniazdo ze NetworkStream) I nie wierzę, że naraża tę funkcję w sposób, który pozwala mieszać go z innymi rodzajami uchwytów czekać.