考虑以下情况
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 :(得分:5)
这可能是一个迟到的答案,但我会这样做(假设您的 Producer 生成一些字符串数据而消费者使用它们)
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);
}
}
}
答案 1 :(得分:2)
为您的消费者收藏集使用BlockingCollection。当没有可用的对象时,它将阻止Take()调用,并在项目可用时立即继续。
编辑(在OP显示它已经在使用BlockingCollection之后): 将TakeTake调用替换为Take阻止调用,直到某个项目可用为止。并一起删除Thread.Sleep调用。
编辑:添加了代码段。
Consumer consumer = consumers.Take();
var result = consumer.Read(data); //do stuff with result
if (consumers.TryAdd(consumer))
{
//ok
}