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>
[..] 块中完成的情况下退出方法Channel
finally
Channel<T>
作为源),那么请考虑通过将其表示为 的自定义实现来返回该序列IAsyncEnumerable<T>
。以方便的表格形式:
ChannelReader<T> |
IAsyncEnumerable<T> |
|
---|---|---|
通常暗示(在 SignalR 之外)具有有限的大小 | 不 | 是的 |
可以无限大小(即可以永远迭代) | 是的 | 是的 |
可以由 SignalR 安全地完成(即停止) | 不 | 是的 |
其他注意事项:
ChannelReader<T>
总是安全的,因为我希望在收到信号时ChannelReader<T>.ReadAllAsync(CancellationToken)
调用,但据我所知,令牌只会取消当前的读取操作,而不会完成本身。ChannelWriter<T>.Complete()
CancellationToken
Channel<T>
Channel<T>
对象,但仅限于它自己创建的对象(在 内部internal class StreamTracker
),而不是当您返回ChannelReader<T>
. 归档时间: |
|
查看次数: |
388 次 |
最近记录: |