2012-09-04 14 views
1

我必須維護信息日誌,這些日誌可以從多個線程同時寫入,但是當我需要它們時,我只使用一個線程來將它列出在取出集合之間需要約5秒鐘的休息時間。最有效的方法來創建在一定的時間戳ConcurrentQueue中的所有現有項目列表

以下是我寫給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的插入方法,它需要List of InformationLog插入數據庫。

這是正確的方法還是有任何其他有效的方法來做到這一點?

+0

如果您每次出院時都將引用設置爲新實例,那麼使用'ConcurrentQueue'有什麼意義? – Jodrell

+0

@Jodrell,更新了我的問題。 –

+1

爲什麼不直接從該線程使用ConcurrentQueue?爲什麼你先把所有的物品都扔到清單上? –

回答

1

您應該使用ConcurrentQueue<T>通過BlockingCollection<T>here所述。


財產以後這樣的,

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

然後在你的消費者線程,你可以做

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

好,這裏是cosuming多發項目的答案。在消費線程爲此,

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,沒有延遲。

inner while循環需要50毫秒超時的項目,這可以根據您的需要進行調整。一旦隊列爲空,它將返回false,然後可以處理一批工作。

+0

BlockingCollection會使用現有的併發隊列進行初始化,並將已排隊的項目複製到它並從併發隊列中將其列出,以便下次我離隊時它不應存在 –

+0

我不想阻止該呼叫,如果沒有項目在那裏,沒問題。 –

+0

'BlockingCollection'應該用於包裝'ConcurrentQueue','ConcurrentBag'和'ConcurrentStack'或其他'IProducerConsumer'的實現者。 http://msdn.microsoft.com/en-us/library/dd997305.aspx – Jodrell

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>對象。

相關問題