C# 单生产者多消费者实现
考虑以下情况C# 单生产者多消费者实现,c#,multithreading,C#,Multithreading,考虑以下情况 private BlockingCollection<Consumer> consumers { get; set; } ThreadPool.QueueUserWorkItem((x) => { while (consumers.Count == 0) Thread.Sleep(20); Consumer consumer;
private BlockingCollection<Consumer> consumers { get; set; }
ThreadPool.QueueUserWorkItem((x) => {
while (consumers.Count == 0)
Thread.Sleep(20);
Consumer consumer;
if (consumers.TryTake(out consumer)) {
var result = consumer.Read(data);
//do stuff with result
if (consumers.TryAdd(consumer)) {
//ok
}
}
});
private BlockingCollection使用者{get;set;}
ThreadPool.QueueUserWorkItem((x)=>{
而(consumers.Count==0)
睡眠(20);
消费者;
if(消费者.尝试获取(消费者){
var结果=消费者读取(数据);
//用结果做事
if(消费者。TryAdd(消费者)){
//嗯
}
}
});
当没有消费者可用于处理请求时,是否有方法避免此超时?为消费者集合使用。当没有可用对象时,它将阻止调用,并在项目可用时立即继续
编辑(OP显示其已在使用BlockingCollection后):
将TryTake调用替换为call to Take,该调用在项目可用之前不会阻塞。然后取下线,一起睡觉
编辑:添加了代码段
Consumer consumer = consumers.Take();
var result = consumer.Read(data); //do stuff with result
if (consumers.TryAdd(consumer))
{
//ok
}
这可能是一个迟来的答案,但我会这样做(假设您的生产者生成一些字符串数据,消费者使用它们)
公共类PC机
{
常量int线程=5;
静态BlockingCollection_Collection=新BlockingCollection();
公共PC()
{
//1生产商
Task.Run(()=>Producer());
//N消费者
对于(inti=0;iConsumer());
}
无效生产者()
{
随机rnd=新随机();
while(true)
{
Thread.Sleep(100);//不要淹没我们的案例。。。
//生产它
_Collection.Add(rnd.Next().ToString());
}
}
无效消费者()
{
while(true)
{
string str=_Collection.Take();
//消耗它
WriteLine(“线程\“{0}\”消耗了{1}”,Thread.CurrentThread.ManagedThreadId,str);
}
}
}
如果你使用的是线程。睡眠
你做错了什么。为什么不使用WaitHandle
来阻止线程?您是否尝试过System.Collections.Concurrent.BlockingCollection
,例如,它的容量有限。使用者的类型是什么?您需要考虑使用,以允许消费者获取X个最大项,然后在没有更多项时等待事件items@TonyTheLion使用者是在进行处理时变得不可用的exe文件,这就是为什么我把它们从collection@Chris那么,把它包括在你的问题里怎么样?当OP已经在使用这个时,说“使用这个”是什么意思it@Eser我没有注意到消费者收集声明。也许是在以后的编辑中添加的?@MihaiCaracostea是的,我后来添加了它,因为我认为TryTake和TryAdd足以澄清类型:)sorry@Eser我在安卓应用程序中输入答案时,问题不可见(也不可见其更新)。@MihaiCaracostea好的,请提问以解决问题。很好的答案,使用while(true)消费者中的循环线程是否仍在运行?那会引起什么问题吗?我应该管理它们的状态吗?@Chris循环不会很紧,因为Take()将在没有可用元素时阻塞。将foreach与getconsumineGenumerable()一起使用而不是while也是正确的吗?
public class PC
{
const int THREADS = 5;
static BlockingCollection<string> _Collection = new BlockingCollection<string>();
public PC()
{
//1 producer
Task.Run(()=>Producer());
//N consumer
for (int i = 0; i < THREADS; i++) Task.Run(() => Consumer());
}
void Producer()
{
Random rnd = new Random();
while(true)
{
Thread.Sleep(100); //Not to flood our case...
//Produce it
_Collection.Add(rnd.Next().ToString());
}
}
void Consumer()
{
while(true)
{
string str = _Collection.Take();
//Consume it
Console.WriteLine("Thread \"{0}\" consumed {1}", Thread.CurrentThread.ManagedThreadId, str);
}
}
}