Używam Producer/Consumer Pattern z System.Collection.Concurrent.BlockingCollection<DataTable
> do pobierania danych z bazy danych (producenta) i tworzenia indeksu Lucene na danych (konsumenta).. Blokowanie jednoczesne .Net ma wyciek pamięci?
Producent przechwytuje 10000 rekordów jednocześnie i dodaje zestaw do BlockingCollection<DataTable>
. Konsument (który jest nieco wolniejszy) następnie chwyta te 10000 i tworzy indeks.
Kolekcja blokująca jest ograniczona do 5 <DataTable>
z 10 000 wierszy.
Początkowo program działał świetnie, ale po jego pobraniu około 150000 wierszy zauważyłem, że pamięć moich komputerów jest wyczerpana i spowalnia indeksowanie.
Wygląda na to, że BlockingCollection po ustawieniu elementu nie ustawi podstawowej szczeliny macierzy na null
.
Kod:
private static LuceneIndex index;
private static BlockingCollection<DataTable> blockingCol;
private static void Producer()
{
while (true)
{
//...get next 10000 rows
DataTable data = GetNextSet();
if(data.Row.Count > 0)
blockingCol.Add(products);
else
break;
}
}
private static void Consumer()
{
while (!BlockingCol.IsCompleted || BlockingCol.Count > 0)
{
DataTable data = blockingCol.Take();
index.UpdateIndex(GetLuceneDocs(data));
}
}
public static void Main(System.String[] args)
{
index = new LuceneIndex();
blockingCol = new BlockingCollection<DataTable>(2);
// Create the producer and consumer tasks.
Task Prod = new Task(Producer);
Task Con = new Task(Consumer);
// Start the tasks.
Con.Start();
Prod.Start();
// Wait for both to finish.
try
{
Task.WaitAll(Con, Prod);
}
catch (AggregateException exc)
{
Console.WriteLine(exc);
}
finally
{
Con.Dispose();
Prod.Dispose();
blockingCol.Dispose();
}
}
Czy ktoś może potwierdzić z odrzucić tę zawieszenie? Czy jest jakaś praca?
Jestem na .net 4.5. W rzeczywistości używam kolekcji poddźwiękowej zamiast datatable. Po prostu włączyłem datatables w tym przykładzie dla uproszczenia. Wypróbuję twoje rozwiązanie. – NSjonas
Myślę, że to nie jest naprawione (prawdopodobnie zapamiętałem). Sam widziałem ten problem. – usr
Wrapper wrapper = BlockingCol.Take(); // do rzeczy wrapper.Item = null; To masz na myśli, prawda? –
NSjonas