C# 8 异步流与 REST/RPC
C# 8 Async Streams vs REST/RPC
我确定这个问题会证明我的无知,但我很难理解这一点。我愿意问一个愚蠢的问题来得到一个好的答案。
我读过的所有关于异步流的 posts 都很好地展示了该功能,但它们没有解释为什么它比替代方案有所改进。
或者,也许,什么时候应该在良好的旧客户端-服务器通信上使用异步流?
我可以看到流式传输大文件内容的地方可能适合异步流,但我看到的许多示例都使用异步流来传输少量传感器数据(例如温度) .似乎带有温度传感器的 IoT 设备可以将数据通过 HTTP POST 发送到服务器,然后服务器可以响应。为什么在那种情况下服务器要实现异步流?
当你努力理解这些话时,我已经能感受到你的痛苦,但请怜悯我。 :)
根据要求,这里有一些我遇到的让我感到困惑的例子。当我找到它们时,我会 post 更多,但我想继续让你开始:
- .NET Conf 主题演讲的前半部分是一个大规模的异步流演示...我不明白他们为什么在这里使用异步流:https://www.youtube.com/watch?v=1xQE2bWkwjo&list=PLReL099Y5nRd04p81Q7p5TtyjCrj9tz1t&index=4&t=
- Here's another example 让我很困惑
我想写一篇专业的回复,但可能也需要粗略的回复:
忘了你听说过 async streams
。他们在想什么?
称它为await foreach
,或async enumerables
或async iterators
。它与IO和流无关。
使用该术语是因为它存在于其他语言中,而不是因为它与 IO 有任何关系。例如,在 Java 中,流是 Java 对 C# 的 IEnumerable 的实现。因此,为了便于未来 Android 开发人员采用,C# 采用了 Java 的坏主意。
我们可以看看语言设计会议,我猜这个术语的实际理由。
认真的原创回答
没有 vs
。这就像对比自动变速箱和汽车。汽车可以有个自动变速箱,它们不能用来代替变速箱。
异步流 纯粹是一个允许创建异步迭代的编程概念。这是允许我们编写此代码以在循环中进行 HTTP 调用并在结果到达时处理结果的功能:
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;
}
}
当它们作为操作结果出现时,仅允许 ASP.NET 核心中间件在生成结果时开始处理结果,它们不会影响 HTTP 响应本身的内容。
另一方面,gRPC 的流 允许服务器向客户端异步发送单独的响应。 gRPC and C# 8 Async stream and Steve Gordon in Server Streaming with GRPC and .NET Core 中的 Laurent Kempe 展示了如何将它们一起使用
从 Steve Gordon 的示例中复制,假设我们有一个向客户端发送预报的天气服务,whose proto file 包含:
service WeatherForecasts {
rpc GetWeather (google.protobuf.Empty) returns (WeatherReply);
rpc GetWeatherStream (google.protobuf.Empty) returns (stream WeatherData);
rpc GetTownWeatherStream (stream TownWeatherRequest) returns (stream TownWeatherForecast);
}
在 C# 8 之前,the client 必须阻塞,直到它在处理它们之前收到所有响应:
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
}
不过在 C# 8 中,可以在响应到达时接收和处理响应:
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
}
**
我确定这个问题会证明我的无知,但我很难理解这一点。我愿意问一个愚蠢的问题来得到一个好的答案。
我读过的所有关于异步流的 posts 都很好地展示了该功能,但它们没有解释为什么它比替代方案有所改进。
或者,也许,什么时候应该在良好的旧客户端-服务器通信上使用异步流?
我可以看到流式传输大文件内容的地方可能适合异步流,但我看到的许多示例都使用异步流来传输少量传感器数据(例如温度) .似乎带有温度传感器的 IoT 设备可以将数据通过 HTTP POST 发送到服务器,然后服务器可以响应。为什么在那种情况下服务器要实现异步流?
当你努力理解这些话时,我已经能感受到你的痛苦,但请怜悯我。 :)
根据要求,这里有一些我遇到的让我感到困惑的例子。当我找到它们时,我会 post 更多,但我想继续让你开始:
- .NET Conf 主题演讲的前半部分是一个大规模的异步流演示...我不明白他们为什么在这里使用异步流:https://www.youtube.com/watch?v=1xQE2bWkwjo&list=PLReL099Y5nRd04p81Q7p5TtyjCrj9tz1t&index=4&t=
- Here's another example 让我很困惑
我想写一篇专业的回复,但可能也需要粗略的回复:
忘了你听说过 async streams
。他们在想什么?
称它为await foreach
,或async enumerables
或async iterators
。它与IO和流无关。
使用该术语是因为它存在于其他语言中,而不是因为它与 IO 有任何关系。例如,在 Java 中,流是 Java 对 C# 的 IEnumerable 的实现。因此,为了便于未来 Android 开发人员采用,C# 采用了 Java 的坏主意。
我们可以看看语言设计会议,我猜这个术语的实际理由。
认真的原创回答
没有 vs
。这就像对比自动变速箱和汽车。汽车可以有个自动变速箱,它们不能用来代替变速箱。
异步流 纯粹是一个允许创建异步迭代的编程概念。这是允许我们编写此代码以在循环中进行 HTTP 调用并在结果到达时处理结果的功能:
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;
}
}
当它们作为操作结果出现时,仅允许 ASP.NET 核心中间件在生成结果时开始处理结果,它们不会影响 HTTP 响应本身的内容。
另一方面,gRPC 的流 允许服务器向客户端异步发送单独的响应。 gRPC and C# 8 Async stream and Steve Gordon in Server Streaming with GRPC and .NET Core 中的 Laurent Kempe 展示了如何将它们一起使用
从 Steve Gordon 的示例中复制,假设我们有一个向客户端发送预报的天气服务,whose proto file 包含:
service WeatherForecasts {
rpc GetWeather (google.protobuf.Empty) returns (WeatherReply);
rpc GetWeatherStream (google.protobuf.Empty) returns (stream WeatherData);
rpc GetTownWeatherStream (stream TownWeatherRequest) returns (stream TownWeatherForecast);
}
在 C# 8 之前,the client 必须阻塞,直到它在处理它们之前收到所有响应:
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
}
不过在 C# 8 中,可以在响应到达时接收和处理响应:
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
}
**