Ho un TransformManyBlock
con il seguente disegno:blocco TPL Dataflow consuma tutta la memoria disponibile
- ingresso: Percorso al file
- uscita: IEnumerable del contenuto del file, una riga alla volta
Sto eseguendo questo blocco su un file enorme (61 GB), che è troppo grande per adattarsi alla RAM. Per evitare una crescita illimitata della memoria, ho impostato BoundedCapacity
su un valore molto basso (ad es. 1) per questo blocco e su tutti i blocchi downstream. Nondimeno, il blocco apparentemente preannuncia avidamente l'IEnumerable, che consuma tutta la memoria disponibile sul computer, interrompendo ogni processo. L'OutputCount del blocco continua ad aumentare senza vincoli finché non uccido il processo.
Cosa posso fare per impedire al blocco di consumare il IEnumerable
in questo modo?
EDIT: Ecco un programma di esempio che illustra il problema:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
class Program
{
static IEnumerable<string> GetSequence(char c)
{
for (var i = 0; i < 1024 * 1024; ++i)
yield return new string(c, 1024 * 1024);
}
static void Main(string[] args)
{
var options = new ExecutionDataflowBlockOptions() { BoundedCapacity = 1 };
var firstBlock = new TransformManyBlock<char, string>(c => GetSequence(c), options);
var secondBlock = new ActionBlock<string>(str =>
{
Console.WriteLine(str.Substring(0, 10));
Thread.Sleep(1000);
}, options);
firstBlock.LinkTo(secondBlock);
firstBlock.Completion.ContinueWith(task =>
{
if (task.IsFaulted) ((IDataflowBlock) secondBlock).Fault(task.Exception);
else secondBlock.Complete();
});
firstBlock.Post('A');
firstBlock.Complete();
for (; ;)
{
Console.WriteLine("OutputCount: {0}", firstBlock.OutputCount);
Thread.Sleep(3000);
}
}
}
Se siete su una scatola a 64 bit, assicurarsi di deselezionare l'opzione "Preferisco a 32 bit" in Visual Studio. Ho 16 GB di RAM sul mio computer e questo programma consuma immediatamente ogni byte disponibile.
ben TBH: non ho tempo per discutere con voi qui - buona fortuna – Carsten
OK, grazie per l'input comunque. – brianberns
se leggi attentamente il resto della sezione vedrai che non funziona come pensi tu - il tuo 'firstBlock' offre sempre tutto ciò che può produrre - se leghi il secondo si rifiuterà il secondo input e lo recupererà in seguito – Carsten