Cow*_*org 6 c# asp.net-core system.threading.channels
我会保持这个简短
阅读“在 ASP.NET Core SignalR 中使用流式传输”一文(第一部分,服务器到客户端流式传输)后, ChannelReader[T]和IAsyncEnumerable[T]之间有什么区别?
好吧,细微的区别是:
ChannelReader<T>是一个abstract class。IAsyncEnumerable<T>是一个协变 interface。ChannelReader<T>- 就像任何人都可以实现一样IAsyncEnumerable<T>-实际上,您只会使用从 . 返回internal的具体子类。ChannelReader<T>Channel<T>.Reader虽然ChannelReader<T>没有实现IAsyncEnumerable<T>,但它确实通过其方法公开了IAsyncEnumerable<T> 自身的视图ReadAllAsync。
笔者(合理)认为两者之间的默示合同存在差异:
IEnumerable<T>(包括IAsyncEnumerable<T>),人们普遍期望其IEnumerable<T>具有有限的大小(即,最终foreach( var x in someEnumerable ) {} 将完成而不是永远循环)...Channel<T>(这是 a 的来源ChannelReader<T>)可能永远不会完成。ChannelReader<T>:
List<T> list = new List<T>();
await foreach( var x in myChannelReader.ReadAllAsync() ) list.Add( x );
Run Code Online (Sandbox Code Playgroud)
ChannelReader<T>(最终)调用了 该ChannelWriter<T>.Complete()方法,这确保了事情不会失控。
ChannelReader<T>对象,则该对象的接收者无法ChannelReader<T>到达底层Channel<T>或其姐妹ChannelWriter<T>对象,因此该ChannelWriter<T>.Complete()方法将永远不会被调用。
IAsyncEnumerable<T> ,因为它可以由其使用者取消/中止,而ChannelReader<T> 不能。
异步迭代器方法避免了 Channel 常见的问题,例如没有足够早地返回 ChannelReader 或在没有完成
ChannelWriter<T>[..] 块中完成的情况下退出方法Channelfinally
Channel<T>作为源),那么请考虑通过将其表示为 的自定义实现来返回该序列IAsyncEnumerable<T>。以方便的表格形式:
ChannelReader<T> |
IAsyncEnumerable<T> |
|
|---|---|---|
| 通常暗示(在 SignalR 之外)具有有限的大小 | 不 | 是的 |
| 可以无限大小(即可以永远迭代) | 是的 | 是的 |
| 可以由 SignalR 安全地完成(即停止) | 不 | 是的 |
其他注意事项:
ChannelReader<T>总是安全的,因为我希望在收到信号时ChannelReader<T>.ReadAllAsync(CancellationToken)调用,但据我所知,令牌只会取消当前的读取操作,而不会完成本身。ChannelWriter<T>.Complete()CancellationTokenChannel<T>Channel<T>对象,但仅限于它自己创建的对象(在 内部internal class StreamTracker),而不是当您返回ChannelReader<T>.| 归档时间: |
|
| 查看次数: |
388 次 |
| 最近记录: |