kasperhj
kasperhj

Reputation: 10482

Stream reading with await async

I have written the following method to read data from a stream in general. On my computer it's gonna be a MemoryStream, and in the real world, it's gonna be a network stream.

    public async void ReadAsync()
    {
        byte[] data = new byte[1024];
        int numBytesRead = await _stream.ReadAsync(data, 0, 1024);

        // Process data ...

        // Read again.
        ReadAsync();
    }

The idea here is that data gets processed in the callback, and the callback should then spawn a new reader-thread (and kill the old). This does not happen however. I get a StackOverflowException.

What am I doing wrong?

Upvotes: 2

Views: 19172

Answers (3)

Filip Ekberg
Filip Ekberg

Reputation: 36287

You've got a never-ending recursion.

You're calling ReadAsync() forever and never return from the method (hence breaking the infinite recursion).

A possible solution is:

public async void ReadAsync()
{
    byte[] data = new byte[1024];
    int numBytesRead = await _stream.ReadAsync(data, 0, 1024);

    // Process data ...

    // Read again.
    if(numBytesRead > 0)
    {
        ReadAsync();
    }
}

To understand recursion better, check this.

Upvotes: 12

Stephen Cleary
Stephen Cleary

Reputation: 456332

There are no threads directly involved here (see my intro to async/await).

Your StackOverflowException is caused (as it usually is) by recursion that goes too deep. Just re-write the method to be iterative:

public async Task ReadAsync()
{
  byte[] data = new byte[1024];

  while (true)
  {
    int numBytesRead = await _stream.ReadAsync(data, 0, 1024);
    if (numBytesRead == 0)
      return;

    // Process data ...
  }
}

Upvotes: 8

Arsen Mkrtchyan
Arsen Mkrtchyan

Reputation: 50712

You need at least to check if there is a data in stream, to repeat operation or your recursion never stops

// Read again.
if(numBytesRead != 0)
    ReadAsync();

Upvotes: 3

Related Questions