Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Правильнее не закрывать канал.
//========================
public async Task ChannelRunWriter(int delayMs, int numberOfReaders,
int howManyMessages = 10, int maxCapacity = 10)
{
_channel = Channel.CreateBounded<string>(maxCapacity);
var writer = _channel.Writer;
for (int i = 0; i < howManyMessages; i++)
{
Console.WriteLine($"2)Writing at {DateTime.Now.ToLongTimeString()}");
await writer.WriteAsync($"[2]SomeText message '{i}");
}
writer.Complete();
}
//============================
public static async Task ChannelRunReader(int delayMs, int numberOfReaders,
int howManyMessages = 100, int maxCapacity = 10)
{
var finalDelayMs = 25;
var finalNumberOfReaders = 1;
var reader = channel.Reader;
async Task Read(ChannelReader<string> theReader, int readerNumber)
{
while (await theReader.WaitToReadAsync())
{
while (theReader.TryRead(out var theMessage))
{
Console.WriteLine($"*** Reader {readerNumber} read '{theMessage}' at {DateTime.Now.ToLongTimeString()}");
await Task.Delay(delayMs);
}
}
}
var tasks = new List<Task>();
for (int i = 0; i < finalNumberOfReaders; i++)
{
tasks.Add(Task.Run(() => Read(reader, i + 1)));
await Task.Delay(10);
}
await reader.Completion;
await Task.WhenAll(tasks);
}
Вот тут закрытие: writer.Complete();
. Очевидно, что после Complete в канал ничего записать уже нельзя, для того этот метод и сделан. Как сообщает Капитан Очевидность, если в канал планируется записывать что-то ещё — не надо вызывать Complete.
Кстати, делать WaitToReadAsync + TryRead в нескольких потоках — не лучшая идея, это ведет к Thundering herd problem, в таких случаях лучше вызывать простой ReadAsync.
System.Threading.Channels — высокопроизводительный производитель-потребитель и асинхронность без аллокаций и стэк дайва