I have a Task that should continuously read from a Tcp stream and place the data into a ConcurrentQueue for processing. Stepping through the function I notice that the ReadAsync Call does not return.
For reference there is no data currently going across the network but I would still like to attempt to read from the stream so long as the loop is active.
Receive Loop
If I step through this loop, I make it to the _stream.ReadAsync line and then the application window pops up skipping the rest of the loop.
private async Task ReceiveLoop()
{
byte[] buffer = new byte[1024];
while (_isConnected)
{
if(_stream != null && _stream.CanRead)
{
try
{
int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
byte[] receivedData = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, receivedData, 0, bytesRead);
if(_receiveQueue != null)
{
_receiveQueue.Enqueue(receivedData);
}
}
}
catch (ObjectDisposedException ex)
{
// Log[Error] - ex
_isConnected = false;
}
catch(InvalidOperationException ex)
{
//Log[Warning] - ex
}
}
// Console.WriteLine("ReceiveLoop is alive");
}
}
1 Answer 1
I notice that the ReadAsync Call does not return.
That is normal and expected. ReadAsync has four expected outcomes:
- either immediately or after some time (synchronous for Read, asynchronous for ReadAsync) reads some positive amount of data
- it returns a non-positive result to indicate an EOF condition
- it results in an exception for a non-graceful failure
- in a niche zero-length read case (provided a zero-length buffer to populate), it returns zero to indicate that data is now available to be read, or an EOF - perform another read with a non-empty buffer to find out which (this scenario is somewhat OS-dependent)
If no data is available, the stream hasn't terminated, and nothing has exploded: we expect ReadAsync to simply not return (or rather: to return an incomplete awaitable).
Comments
Explore related questions
See similar questions with these tags.
awaited somewhere. Side notes:_stream != nullis always true. You should break out of the loop withif (bytesRead == 0) break;which will only happen if the socket is closed. Instead of_isConnectedjustbreak;out of the loop or throw.