Sto utilizzando un Producer/Consumer Pattern con un System.Collection.Concurrent.BlockingCollection<DataTable
> per recuperare dati da un database (produttore) e creare un indice Lucene sui dati (consumatore).Il .Net Concurrent BlockingCollection ha una perdita di memoria?
Il produttore acquisisce 10000 record alla volta e aggiunge set allo BlockingCollection<DataTable>
. Il consumatore (che è un po 'più lento) afferra quei 10000 e crea un indice.
La raccolta di blocchi è limitata a 5 <DataTable>
di 10000 righe ciascuno.
All'inizio il programma funziona alla grande, ma dopo aver ottenuto circa 150000 righe ho notato che la memoria del mio computer è al massimo e rallenta a passo d'uomo.
Sembra che BlockingCollection non riesca a impostare lo slot dell'array sottostante su null
dopo l'acquisizione dell'elemento.
Codice:
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();
}
}
Can
chiunque conferma di rifiutare questa sospensione? E c'è qualche problema?
Sono su .net 4.5. In realtà sto usando una collezione subsonica anziché datatable. Ho appena incluso i datatables in questo esempio per semplicità. Proverò la tua soluzione. – NSjonas
Suppongo che non sia corretto allora (probabilmente mi sono ricordato). Ho visto questo problema me stesso, però. – usr
Wrapper wrapper = BlockingCol.Take(); // do stuff wrapper.Item = null; Questo è ciò che intendi giusto? –
NSjonas