最有效的方法是在特定时间戳创建ConcurrentQueue中所有现有项的列表

时间:2012-09-04 07:56:38

标签: c#

我必须维护信息日志,这些日志可以同时从多个线程写入,但是当我需要它们时,我只使用一个线程将它出列,它会在出列集合之前中断大约5秒。

以下是我写给Dequeue的代码。

if (timeNotReached)
{
   InformationLogQueue.Enqueue(informationLog);
}
else
{
    int currentLogCount = InformationLogQueue.Count;
            var informationLogs = new List<InformationLog>();
            for (int i = 0; i < currentLogCount; i++)
            {
                InformationLog informationLog1;
                InformationLogQueue.TryDequeue(out informationLog1);
                informationLogs.Add(informationLog1);
            }
    WriteToDatabase(informationLogs);
}

出列后我将它传递给LINQ的insert方法,该方法需要将InformationLog List插入数据库。

这是正确的方式还是有其他有效的方法来做到这一点?

2 个答案:

答案 0 :(得分:1)

您应该按BlockingCollection<T>所述的here使用ConcurrentQueue<T>


像这样的事,

private BlockingCollection<InformationLog> informationLogs = 
    new BlockingCollection<InformationLog>(new ConcurrentQueue<InformationLog>);

然后在你的消费者线程上你可以做

foreach(var log in this.informationLogs.GetConsumingEnumerable())
{
    // process consumer logs 1 by 1. 
}

好的,这是一个用于消耗多项的答案。在消费线程上执行此操作,

InformationLog nextLog;
while (this.informationLogs.TryTake(out nextLog, -1))
{
    var workToDo = new List<informationLog>();
    workToDo.Add(nextLog);

    while(this.informationLogs.TryTake(out nextLog))
    {
        workToDo.Add(nextLog);
    }

    // process workToDo, then go back to the queue.
}

第一个while循环从队列中获取无限等待时间的项目,我假设一旦队列中的添加完成,即调用CompleteAdding,此调用将返回false,没有延迟,一旦队列为空。

内部while循环占用50毫秒超时的项目,可以根据需要进行调整。一旦队列为空,它将返回false,然后可以处理这批工作。

答案 1 :(得分:0)

您可以通过以下扩展方法直接在Linq语句中使用ConcurrentQueue<T>

static IEnumerable<T> DequeueExisting<T>(this ConcurrentQueue<T> queue)
{
    T item;
    while (queue.TryDequeue(out item))
        yield return item;
}

这样可以避免不必分配新的List<T>ConcurrentQueue<T>对象。