繁体   English   中英

线程安全缓冲区

[英]Thread-safe buffer

我正在实现某种缓冲机制:

private static readonly ConcurrentQueue<ProductDto> ProductBuffer = new ConcurrentQueue<ProductDto>();

private async void On_ProductReceived(object sender, ProductReceivedArgs e)
{
    ProductBuffer.Enqueue(e.Product);

    if (ProductBuffer.Count >= handlerConfig.ProductBufferSize)
    {
        var products = ProductBuffer.ToList();
        ProductBuffer.Clear();

        await SaveProducts(products);
    }
}

问题是-我是否应该麻烦地添加某种锁,以确保没有数据丢失(假设某些其他线程会在buffer.ToList()之后和buffer.Clear()之前添加乘积,假设是:),或ConcurrentQueue将为我处理所有肮脏的工作?

您可以这样做:

if (ProductBuffer.Count < handlerConfig.ProductBufferSize)
    return;

var productsToSave = new List<Product>();
Product dequeued = null;
while(ProductBuffer.TryDequeue(out dequeued))
{
    productsToSave.Add(dequeued);
}
SaveProducts(products);

您永远不会Clear队列。 您只要不断取出东西,直到它变空为止。 如果您不想一次保存太多产品,或者当productsToSave达到一定大小时可以停止处理,处理该列表,然后开始新的列表。

这样,是否将新项目添加到队列都没有关系。 如果在您从队列中读取时添加了它们,它们也会被读取。 如果是在您停止从队列中读取后才添加的,则它们将在那里并在队列下一次充满并处理时读取。

ConcurrentQueue的要点是,您可以添加到其中并从多个线程中读取它,而无需lock


如果要这样做:

    productsToSave = ProductBuffer.ToList();

    ProductBuffer.Clear();

那么您将需要该lock (这将无法达到目的。)大概您正在使用ConcurrentQueue因为可能有多个线程将项目添加到队列中。 如果真是这样,那么在这两个语句的执行之间完全有可能进入队列。 它不会添加到列表中,但会被Clear删除。 该项目将丢失。

这是我要实现的方式,我假设不需要在保存完成时通知您?

private void On_ProductReceived(object sender, ProductReceivedArgs e)
{
    // Variable to hold potential list of products to save
    List<Products> productsToSave;

    // Lock buffer
    lock(ProductBuffer)
    {
        ProductBuffer.Enqueue(e.Product);

        // If it is under size, return immediately
        if (ProductBuffer.Count < handlerConfig.ProductBufferSize)
            return;

        // Otherwise save products, clear buffer, release lock.
        productsToSave = ProductBuffer.ToList();

        ProductBuffer.Clear();
    }

    // Save Produts, 

    SaveProducts(products);
}

如果您只获得1种产品,而又什么也没有得到,怎么办?您是否不想在超时后保存该产品?

我会在您的用例中使用Rx东西,尤其是IObservable<T>.Buffer(count)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM