Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - Datagridview in iText.NET
Forum - C# / VB.NET - Datagridview in iText.NET

Avatar
growning (Normal User)
Rookie


Messaggi: 22
Iscritto: 17/06/2009

Segnala al moderatore
Postato alle 11:45
Lunedì, 16/11/2009
Ciao, ho un problema con l'esportazione di dati da un dgv ad un pdf, utilizzando iText.

Praticamente una volta che parte l'esportazione, ovviamente più sono i dati contenuti della dgv e più tempo ci mette, e fin qui vabene, solo che oltre a più tempo, la memoria utilizzata dal processo del programma cresce a dismisura.

Con 5000 righe (circa) sfiora i 250MB di spazio.

Ho fatto la prova con 60000 righe e sono arrivato a 700MB :-|.

Quindi più righe ci sono, più l'eccezione (incubo) OutOfMemory si avvicina.

Questo è un esempio di codice che utilizzo per passare i dati dalla dgv alla Table del documento pdf:

Codice sorgente - presumibilmente VB.NET

  1. Dim tbh As New Table(dgv.ColumnCount)
  2. Dim cel As New Cell
  3. with tbh
  4.  For irow As Integer = 0 To dgv.RowCount - 1
  5.                 For icol As Integer = 0 To dgv.ColumnCount - 1
  6.                                     cel = New Cell(dgv.Item(icol, irow).Value)
  7.                                     .addCell(cel)
  8. next
  9. next
  10. end with



Qualcuno ha qualche idea per evitare che la memoria utilizzata dal mio processo cresca così tanto da rischiare di generare un outofmemory?


PM Quote
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 12:21
Lunedì, 16/11/2009
Conta che crei un nuovo oggetto per ogni cella, quindi 60.000 * numero di colonne * memoria occupata da una cella: non è poco.
Conta che un oggetto tiene come minimo 6 bytes di memoria, e una stringa almeno 20 bytes (più 2 bytes per carattere). Supponendo che tu abbia solo cinque colonne, e che ogni cella contenga SOLO una stringa vuota (il che è impossibile, poiché conterrà molte altre proprietà e molti altri campi privati e una stringa non nulla), occuperai almeno 7.8 MB.

PM Quote
Avatar
growning (Normal User)
Rookie


Messaggi: 22
Iscritto: 17/06/2009

Segnala al moderatore
Postato alle 12:48
Lunedì, 16/11/2009
Testo quotato

Postato originariamente da Il Totem:

Conta che crei un nuovo oggetto per ogni cella, quindi 60.000 * numero di colonne * memoria occupata da una cella: non è poco.
Conta che un oggetto tiene come minimo 6 bytes di memoria, e una stringa almeno 20 bytes (più 2 bytes per carattere). Supponendo che tu abbia solo cinque colonne, e che ogni cella contenga SOLO una stringa vuota (il che è impossibile, poiché conterrà molte altre proprietà e molti altri campi privati e una stringa non nulla), occuperai almeno 7.8 MB.



Ho provato con uno stringbuilder, ma senza successo.

E non c'è nessun modo per risolvere questo problema?


PM Quote
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 12:56
Lunedì, 16/11/2009
Lo StringBuilder è notevolmente più veloce nella manipolazione, ma i dati memorizzati sono sempre gli stessi.

Per quanto mi sembra di capire dal tuo codice, non c'è niente che tu possa fare. Al massimo puoi provare a invocare GC.Collect() dopo ogni riga, ma usare i metodi del garbage collector è fortemente sconsigliato. Una soluzione intelligente, ma non compatibile col tuo caso, sarebbe quella di scrivere sequenzialmente i dati dalla grid al file: ossia prendi la cella (0,0), scrivi nel file il codice per disegnare quella cella, poi prendi la (0,1) e così via. Sarebbe comunque difficile anche senza una libreria, poiché i pdf contengono dati compressi a blocchi.

PM Quote
Avatar
growning (Normal User)
Rookie


Messaggi: 22
Iscritto: 17/06/2009

Segnala al moderatore
Postato alle 9:43
Martedì, 17/11/2009
Testo quotato

Postato originariamente da Il Totem:

Lo StringBuilder è notevolmente più veloce nella manipolazione, ma i dati memorizzati sono sempre gli stessi.

Per quanto mi sembra di capire dal tuo codice, non c'è niente che tu possa fare. Al massimo puoi provare a invocare GC.Collect() dopo ogni riga, ma usare i metodi del garbage collector è fortemente sconsigliato. Una soluzione intelligente, ma non compatibile col tuo caso, sarebbe quella di scrivere sequenzialmente i dati dalla grid al file: ossia prendi la cella (0,0), scrivi nel file il codice per disegnare quella cella, poi prendi la (0,1) e così via. Sarebbe comunque difficile anche senza una libreria, poiché i pdf contengono dati compressi a blocchi.



Scusa l'ignoranza, perchè è sconsigliato usare metodi del garbage collector?

PM Quote
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 16:07
Martedì, 17/11/2009
E' una forzatura: il processo di GC dovrebbe essere gestito solamente dal CLR e il programmatore non dovrebbe intervenire. In questo caso, Collect() diminuirebbe di molto le prestazioni del codice: inoltre, delle GC ripetute potrebbero erroneamente eliminare oggetti relativamente giovani a causa della rapida processione delle generazioni.

PM Quote