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);
        }
    }
}