I have an UnboundedChannel
single reader\multiple writers and I want to be able to use Count
property, but since CanCount
property is always false Count
is throwing an exception. What should i do to make it work, i can't find any restrictions enlisted in docs.

- 10,423
- 1
- 11
- 29

- 508
- 6
- 15
-
Why do you want to know that? Whatever the actual problem is probably doesn't require knowing the count. For example, to batch messages you can retrieve them one by one and add them to a local list until you reach the limit. You could also use the LINQ operators in the [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async/) package along with `ChannelReader.ReadAllAsync()`, – Panagiotis Kanavos Dec 17 '21 at 12:26
2 Answers
When the UnboundedChannelOptions.SingleReader
property is set to true
on creation, the UnboundedChannel
implementation is SingleConsumerUnboundedChannel
. Based on the source, the Reader
object used by this class extends ChannelReader
without explicitly setting CanCount
, which is set to false
by ChannelReader
by default.
Unfortunately all these classes are sealed so you can't just extend them and implement Count
yourself. Leaving the SingleReader
option as false
will use an UnboundedChannelReader
implementation that does set CanCount
to true
and implements a Count
method. If you just need to check whether there are more elements in the queue, you could also use TryPeek
instead.

- 3,105
- 2
- 14
- 17
-
Thanks, i haven't noticed i was acutally using SingleConsumerUnboundedChannel in this configuration, now with default options it works. I wonder why CanCount set to false with single reader. – cookieMonster Dec 17 '21 at 09:09
-
@cookieMonster The implementation of [`SingleProducerConsumerQueue`](https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/Common/src/System/Collections/Concurrent/SingleProducerConsumerQueue.cs) implements `Count` but says "This method is not safe to use concurrently with any other members that may mutate the collection." My best guess is that the designers decided not to expose it rather than open up the concurrency error risk. – IllusiveBrian Dec 17 '21 at 12:56
All bounded channel implementations support reading the Count
, so if you need a SingleReader
and Count
-enabled unbounded channel you could just use a bounded channel configured with the maximum capacity. Practically it will be unbounded.
var channel = Channel.CreateBounded<int>(
new BoundedChannelOptions(Int32.MaxValue) { SingleReader = true });
Console.WriteLine(channel.Reader.CanCount); // True
Update: Currently there is only one bounded channel implementation, the BoundedChannel<T>
(internal sealed class), which ignores the SingleReader
setting. In other words you get the same implementation, regardless of the number of readers that you want to use. Which is a bit disappointing, because it indicates that the rich set of available options does not correspond to an equally rich set of implementations. Basically there are only three implementations available in .NET 6, the UnboundedChannel<T>
, the SingleConsumerUnboundedChannel<T>
, and the BoundedChannel<T>
.

- 34,835
- 7
- 69
- 104