2015-09-12 47 views
-2

考虑下列情形单生产者多消费者的实现

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

是否有办法避免这种超时的时候没有提供一个消费者来处理请求?

+0

如果你使用'主题睡觉,你做错了什么。为什么不使用'WaitHandle'来代替线程呢? – Dai

+1

你有没有试过'System.Collections.Concurrent.BlockingCollection'为前。它有一个有限的能力。 – Eser

+0

'消费者'的类型是什么?你需要考虑使用[semaphore](https://msdn.microsoft.com/en-us/library/system.threading.semaphore%28v=vs.110%29.aspx)来允许消费者获取X项目max,然后在没有更多项目时等待事件 –

回答

2

为您的消费者收藏使用BlockingCollection。当没有物品可用时,它将阻止Take()呼叫,并在物品可用时立即继续。

编辑(在OP显示它已经使用BlockingCollection后): 将TryTake调用替换为Take的调用,它将阻止,直到项目可用。并一起删除Thread.Sleep调用。

编辑:添加代码片段。

Consumer consumer = consumers.Take(); 
var result = consumer.Read(data); //do stuff with result 
if (consumers.TryAdd(consumer)) 
{ 
    //ok 
} 
+1

当OP已经使用它时,说“使用这个”的含义是什么 – Eser

+0

@Eser我没有注意到消费者收集声明。也许在以后的编辑中添加? –

+0

但在你的答案之前... – Eser

5

这可能是一个迟到的答案,但我会做这样(假设你监制产生一些字符串数据和消费者使用它们)

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

这是正确的生产者 - 消费者模式。 –

+0

很好的答案,通过使用消费者中的while(true)循环,线程是否仍在运行?这会导致任何问题吗?我应该管理他们的状态吗? – Hristo

+0

@Chris循环不会很紧,因为Take()会在没有元素可用时阻塞。 –