2017-06-03 49 views
-1

我有一個使用parallel.foreach循環的長時間運行的進程。在該循環中,我基於傳遞的內容創建兩個不同類的實例,執行次要任務,然後添加到線程安全集合。完成後,所有數據都需要插入到sql中。在parallel.foreach循環中清除線程安全集合插入到sql後

我遇到的問題是所做的工作量太大,無法保留在收藏中,直到完成所有處理。我必須偶爾將所保留的內容推送到SQL,然後刪除從集合中推出的內容,以便可以在內存不足的情況下繼續執行更多處理,而且我不知道最佳方式。如果通過檢查集合的數量並且它超過一定數量,我可以輕鬆地做到這一點,請調用一個函數,通過批量插入或值表將內容推送到SQL,然後清除該集合在下一個聲明。在parallel.foreach內完成此操作的最佳方法是什麼?

我打算使用線程安全的任何集合。到目前爲止,我一直在使用ConcurrentQueue並考慮切換到BlockingCollection,因爲我沒有看到清除併發隊列的方法。我不在乎內容的插入順序,但我需要至少能夠刪除推送到sql的內容。

我最好的解決辦法是使用BlockingCollection.GetConsumingEnumerable()。這樣,一旦超過了x的數量,我可以將該集合的內容複製到另一個線程安全集合中,執行我的插入操作,然後使用該列表從BlockingCollection.GetConsumingEnumerable()中刪除原始內容。完成後,處理臨時列表。我只是認爲有更好的辦法,因爲如果我必須一次迭代一個來刪除它,那麼它就會讓它失去多線程的目的。

我已經看到使用pulse and wait的用法,但是我找不到一個看起來很安全的好用例。在我測試集合超過一定數量並在被插入到sql之前得到清除後,我可能會遇到一些問題。

我正在使用4.5框架,我正在管理兩個不同的集合,需要推送但不一定在同一時間。

+1

請看[TPL Dataflow](https://www.google.co.uk/search?q=microsoft+tpl+dataflow)。它包含您需要在程序中協調生產者/消費者流程所需的所有構件,在我看來,它非常適合您所描述的問題。走一小段路,看看它提供了什麼。你不會後悔的。 – spender

回答

1

我不會推薦清除併發集合。相反,我會'替換'一個新的 - 並處理來自舊的內容,而其他線程推送他們的內容到新的。

Interlocked.Exchange是我用來完成這項工作的技術。