liveBook · Manning

Async stream

As explained in .NET in Action, Second Edition

An async enumerable, or async stream, is an asynchronously produced sequence whose elements can be consumed as they become available.

An async stream is a sequence whose elements can be consumed as they become available. In C#, `IAsyncEnumerable<Comic>` lets a repository expose search results as an asynchronous sequence rather than a single `Task` containing the results. section 8.2

Return a repository query

A repository’s `Find` method filters comics by title and calls `AsAsyncEnumerable()` on the EF Core query. Its return type is `IAsyncEnumerable<Comic>`; adding and saving a comic instead uses `Task`-returning methods. section 8.2

Listing 8.6 Operating on an IAsyncEnumerable
private IAsyncEnumerable<Comic> FindComicsByText(
  string searchText) { }                                    #1
  
private async Task<Image> GetComicImageAsync(
  string imgUrl) { }                                        #1
  
public async IAsyncEnumerable<Comic> Find(                  #2
  string searchText)
{
  var foundComics = FindComicsByText(searchText);           #3
  
  await foreach (var comic in foundComics)                  #4
  {
    comic.Image = await GetComicImageAsync(comic.ImgUrl);   #5
    yield return comic;                                     #6
  }
}

Follow the per-element path: `await foreach` reads each comic, an awaited call obtains its image, and `yield return` emits the updated comic. Because this is an async iterator, `Find` returns `IAsyncEnumerable<Comic>` without wrapping it in `Task`. section 8.2

The return type changes when a method awaits preliminary work but does not enumerate the results itself. `FindAsync` fetches missing comics, then returns the repository’s `IAsyncEnumerable<Comic>` as an object. It therefore returns `Task<IAsyncEnumerable<Comic>>`: awaiting the task obtains the sequence; consuming the sequence is a separate step. section 8.4

Test the returned sequence

An integration test awaits `FindAsync("b")`, converts the resulting sequence with `ToBlockingEnumerable()`, and asserts that exactly one matching comic was found. SQLite backs the repository while a faked HTTP message handler supplies responses. section 8.4

How .NET in Action, Second Edition covers it

How deep it goes
Shows EF Core sequence creation and an `await foreach`/`yield return` iterator, but defers a fuller async-stream tutorial.
Examples
Demonstrates title-search results, asynchronous image retrieval for each comic, and a SQLite-backed search test.
What it assumes
Assumes familiarity with C# `async`/`await` and tasks while illustrating how asynchronous sequences are returned and consumed.
What you can do after
Apply it via EF Core to return asynchronous query results and use `await foreach` to enrich them before yielding.
How it connects
Connects `IAsyncEnumerable`, async iterators, `Task`, EF Core queries, and integration testing.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of .NET in Action, Second Edition. The section links point to the parts of the book it draws on.