.net - Hvorfor modtager jeg stadig data, selv efter NetworkStream.EndRead returnerer 0 bytes?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger NetworkStream.BeginRead/EndRead for asynkron læsning fra en stikkontakt.


Men NetworkStream.EndRead () sommetider vender tilbage 0 (dvs. 0 bytes blev læst fra stikkontakten), som jeg troede indikeret stikket blev lukket, men det er ikke sandt, for hvis jeg fortsætter med at kalde BeginRead () får jeg i sidste ende flere data.


Er dette ikke en ordentlig sløjfe til kontinuerligt at læse data fra en stikkontakt/NetworkStream?


void BeginContinousRead()
{
  // Start the continous async read
  mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}

private void ProcessNetworkStreamRead(IAsyncResult result)
{
  // This will sometimes be zero?!
  int bytesRead = mStream.EndRead(result);

  // Continue reading more data and call this callback method again over and over, etc.
  mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}


Ifølge MSDN skal jeg bruge PropertyStream.DataAvailable egenskaben for at afgøre, om der er flere data på stikkontakten, men det vil være FALS, selvom flere data måske kommer til en senere dato.


For eksempel, ifølge MSDN bør dette være min tilbagekaldelse:


private void ProcessNetworkStreamRead(IAsyncResult result)
{
  // This will sometimes be zero?!
  int bytesRead = mStream.EndRead(result);

  while (mStream.DataAvailable)
    mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}


... men det virker ikke korrekt, fordi DataAvailable bliver FALSK, og så fortsætter min kontinuerlige læsning og læser aldrig flere data.


Hvad er den korrekte asynkrone tilgang til at fortsætte med at læse data, indtil den anden ende lukker stikket, eller vælger jeg at lukke stikkontakten?

Bedste reference


I stedet for at kontrollere bytesRead eller DataAvailable egenskaben for at kontrollere om stikket er lukket, skal du indlede opkaldet til BeginRead og fange en IOException. Det skal så fortælle dig, om stikket er lukket.