问题描述
主程序启动一个任务,它是 Channel 的消费者任务。消费者任务代码是:
while (await channelReader.WaitToReadAsync())
{
while(channelReader.TryRead(out item))
{
console.writeline("item is"+item.clientId);
}
}
有套接字服务器。当套接字客户端连接到服务器时,服务器为每个客户端启动任务。每个客户端任务都是通道的生产者。 生产者代码是:
foreach (var item in itemList )
{
item.clientId = clientId;
await drawChannelWriter.WriteAsync(item);
}
发生的情况是:首先接收来自一个客户端的所有元素,然后接收来自其他任务的所有元素。 为什么通道中没有混合不同任务的不同元素?
解决方法
Channels 是一个高性能的异步就绪生产者/消费者队列。 “高性能”位意味着它会尽可能同步完成。
当套接字客户端连接到服务器时,服务器为每个客户端启动任务。每个客户端任务都是频道的生产者。
这很好。我要检查的第一件事是每个客户端是否在单独的线程(例如,Task.Run
)上运行,或者它们是否只是异步任务。
发生的情况是:首先接收来自一个客户端的所有元素,然后接收来自其他任务的所有元素。为什么通道中没有混合不同任务的不同元素?
我希望无界通道上的 WriteAsync
始终同步完成。在内部,它只是将项目添加到队列中,并且由于队列始终有空间(在无界通道中),因此没有任何 AFAIK 可以使 WriteAsync
异步完成。因此,您的产品中的整个 foreach
循环同步运行。
这种行为没有任何错误。如果您的生产者都在不同的线程上运行,那么他们可能会同时运行其 foreach
循环,并且元素可能会交错。但是每个 foreach
循环都会非常运行,因此一个线程很可能会在另一个线程获得机会之前添加其所有项目。