When you run this program, you should see output similar to this:
In this C# version:
We use a BlockingCollection<int> instead of a channel. This provides similar functionality for producer-consumer scenarios.
The CompleteAdding() method is analogous to closing a channel. It signals that no more items will be added.
Instead of a goroutine, we use a Task to represent our worker.
We use a TaskCompletionSource<bool> to signal when the worker is done, which is similar to the done channel in the original example.
The GetConsumingEnumerable() method allows us to iterate over the collection, automatically blocking when no items are available and stopping when the collection is marked as complete.
Finally, we use TryTake() to check if we can receive more jobs after the collection is complete, which is similar to reading from a closed channel.
This example demonstrates how to implement a pattern in C# that’s similar to closing channels in other languages, using the types available in the .NET framework.