BufferBlock <t>不断

时间:2016-07-17 21:54:32

标签: c# multithreading task-parallel-library

我想在ASP.NET请求的上下文中使用BufferBlock<T>实现使用者/生产者模式,但我还需要:

  1. 缓冲'生成'消息以防止队列填满可用内存(一次说缓冲区中有50个项目)
  2. 生产者将持续“生产”,并且它运行的线程将在产生一堆消息后立即关闭。 (当ASP.NET请求结束时)
  3. 消费者将持续“消费”,因为多个生产者(ASP.NET请求)每个都会产生一堆消息,因此我们认为有一个单独的线程可以实现消费。
  4. [组件我最终需要在长期运行的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()事情。

0 个答案:

没有答案