I wanted to write a professional response but the crude one is probably needed too:
Forget you ever heard about async streams
. What were they thinking?
Call it await foreach
, or async enumerables
or async iterators
. It has nothing to do with IO and streams.
The term is used because it exists in other languages, not because it has anything to do with IO. In Java for example, streams are Java's implementation of C#'s IEnumerable. So, to ease adoption by future Android devs, C# adopted Java's bad idea.
We can look at the language design meetings for the actual justification for this term I guess.
Serious original answer
There's no vs
. It's like contrasting automatic gear boxes and cars. Cars can have automatic gear boxes, they aren't used instead of gear boxes.
Async streams is purely a programming concept that allows the creation of async iteratos. It's the feature that allows us to write this to make HTTP calls in a loop and process the results as they arrive :
await foreach(var someValue from someAsyncIterator(5))
{
...
}
IAsyncEnumerable<string> someAsyncIterator(int max)
{
for(int i=0;i<max;i++)
{
var response=await httpClient.GetStringAsync($"{baseUrl}/{i}");
yield return response;
}
}
When they appear as action results it's only to allow the ASP.NET Core middleware to start processing results as they are produced, they don't affect the contents of the HTTP response itself.
gRPC's streams on the other hand allow the server to send individual responses to the client asynchronously. Laurent Kempe in gRPC and C# 8 Async stream and Steve Gordon in Server Streaming with GRPC and .NET Core show how these can be used together
Copying from Steve Gordon's samples, let's say we have a weather service that sends forecasts to the client, whose proto file contains :
service WeatherForecasts {
rpc GetWeather (google.protobuf.Empty) returns (WeatherReply);
rpc GetWeatherStream (google.protobuf.Empty) returns (stream WeatherData);
rpc GetTownWeatherStream (stream TownWeatherRequest) returns (stream TownWeatherForecast);
}
Before C# 8, the client would have to block until it received all responses before processing them:
using var channel = GrpcChannel.ForAddress("https://localhost:5005");
var client = new WeatherForecastsClient(channel);
var reply = await client.GetWeatherAsync(new Empty());
foreach (var forecast in reply.WeatherData)
{
//Do something with the data
}
In C# 8 though, the responses can be received and processed as they arrive :
using var replies = client.GetWeatherStream(new Empty(), cancellationToken: cts.Token);
await foreach (var weatherData in replies.ResponseStream.ReadAllAsync(cancellationToken: cts.Token))
{
//Do something with the data
}
**
await foreach
and IAsyncEnumerable. Nothing at all to do with IO, HTTP and networking. They can be used to make calling gRPC streams easier – Arvillaarvin