有没有办法从阻止集合中批处理一组项目。 E.G。
我有一个消息总线发布者呼叫 blockingCollection.Add()
这是一个像这样创建的消费线程:
Task.Factory.StartNew(() =>
{
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine(value);
}
});
但是,我只希望控制台在阻塞集合上有10个项目后写入,而GetConsumingEnumerable()总是在每个项目添加后触发。我可以为此编写自己的队列但是如果可能的话我想使用阻塞集合吗?
答案 0 :(得分:4)
快速解决方案就是这样的
public class ConsoleQueue
{
private readonly List<string> _values = new List<string>();
public void FlushQueueIfFull()
{
if (_values.Count < 10) return;
foreach (var value in _values)
{
Console.WriteLine(value);
}
_values.Clear();
}
public void Push(string message)
{
_values.Add(message);
FlushQueueIfFull();
}
}
那么你可以像这样使用它
var queue = new ConsoleQueue();
Task.Factory.StartNew(() =>
{
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
queue.Push(value);
}
});
您可以轻松扩展它以涵盖线程安全等
答案 1 :(得分:3)
不确定项目要求是什么,但我建议TPL DataFlow BatchBlock。
您将实例化BatchBlock<string>
,将其绑定到ActionBlock<string>
,然后发布到批处理块。
伪代码可能如下所示:
var bb = new BatchBlock<string>(10);
var ab = new ActionBlock<string[]>(msgArray=>{
foreach(var msg in msgArray)
Console.Writeline(msg);
});
bb.LinkTo(ab);
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
bb.Post(value);
}
使用DataFlow,您甚至可能希望将BlockingCollection替换为BufferBlock,或者只是直接发布到缓冲区块而无需先添加阻塞集合,因为批处理块已经是线程安全的。