我想在ASP.NET请求的上下文中使用BufferBlock<T>
实现使用者/生产者模式,但我还需要:
[组件我最终需要在长期运行的ASP.NET托管REST服务中记录调用,其中每个请求在执行时'生成'许多日志消息,并且消费者最终通过将它们写入某些持久性来“消耗”它们商店(通过网络相对较慢)。]
我们一直在关注Steven Cleary关于使用BufferBlock<T>
here的指导,但似乎所有这些示例都调用了结束消息生成的BufferBlock<T>.Complete()
方法。 (即,一旦调用Complete()
,块就会忽略调用SendAsync()
。)
那么我们如何在“连续”模式下使用BufferBlock<T>
,而消费者在生产者不断生产的同时不断消费?我想没有打电话给Complete()
。
我们正在使用BoundedCapacity
来定义缓冲区:
var _queue = new BufferBlock<TMessage>(new DataflowBlockOptions
{
BoundedCapacity = 50
});
然后......开始消费者:
Task.Run(async () =>
{
while (true)
{
try
{
while (await _queue.OutputAvailableAsync())
{
var message = await _queue.ReceiveAsync();
try
{
_storage.Store(message)
}
catch (Exception)
{
//Log and Ignore exception and continue
}
}
}
catch (Exception)
{
//Log and Ignore exception and continue
}
}
});
因此,随着消费者无休止地运行,我们现在希望不断调用SendAsync()
(由每个ASP.NET请求线程)并使消息排队,而消费者(线程池线程)持续消耗它们
如何使用BufferBlock<T>
或其他TPL类型来实现此目标?
更新(2016年7月22日):
我最终将ActionBlock链接到BufferBlock,只是将委托_storage.Store(message)
传递给ActionBlock以便于维护,并避免整个while循环和Complete()
事情。