PDA

View Full Version : [C#] Popolamento progressivo datagridview


rizzotti91
29-09-2013, 21:58
Ciao, ho necessità di popolare diverse dataGridView con migliaia e migliaia di record a partire da un database.
Al momento adotto un sistema che non tanto mi piace... prelevo i dati dal db, li metto in una datatable e successivamente li faccio visualizzare.
Sul pc in firma anche se ci sono oltre 20.000 righe il caricamento è istantaneo, ma basta andare a provare il software su un pc più "normale" ed un piccolo impuntamento iniziale si percepisce.

Altra nota dolente della mia soluzione è che non riempio la datatable in un thread in background, ciò comporta avere l'interfaccia del tutto bloccata fin quando non è andato il buon fine il prelievo dei dati.
Altro grossissimo problema è quando utilizzo un server mysql via internet per popolare il tutto, dove i tempi di attesa si prolungano per almeno 12-15 secondi durante i quali non si può fare nulla...

Avete qualche soluzione da proporre?

Grazie :)

[Kendall]
30-09-2013, 07:59
Ciao, ho necessità di popolare diverse dataGridView con migliaia e migliaia di record a partire da un database.
Al momento adotto un sistema che non tanto mi piace... prelevo i dati dal db, li metto in una datatable e successivamente li faccio visualizzare.
Sul pc in firma anche se ci sono oltre 20.000 righe il caricamento è istantaneo, ma basta andare a provare il software su un pc più "normale" ed un piccolo impuntamento iniziale si percepisce.

Altra nota dolente della mia soluzione è che non riempio la datatable in un thread in background, ciò comporta avere l'interfaccia del tutto bloccata fin quando non è andato il buon fine il prelievo dei dati.
Altro grossissimo problema è quando utilizzo un server mysql via internet per popolare il tutto, dove i tempi di attesa si prolungano per almeno 12-15 secondi durante i quali non si può fare nulla...

Avete qualche soluzione da proporre?

Grazie :)

Beh, la soluzione l'hai citata pure tu. Genera la DataTable tramite una query in background (E magari nel mentre che esegui la query visualizzi una barra di caricamento continua), quindi al termine di essa imposti la DataSource della tabella con il DataTable appena generato.

L'infrastruttura per i Thread in C# è una goduria, e l'introduzione degli operatori await e async ha reso il tutto di una banalità unica (anche se è sempre meglio darsi una bella letta alla gestione delle operazioni asincrone prima dell'introduzione di questi operatori, per capire davvero come funziona il tutto).

rizzotti91
30-09-2013, 11:33
;40039342']Beh, la soluzione l'hai citata pure tu. Genera la DataTable tramite una query in background (E magari nel mentre che esegui la query visualizzi una barra di caricamento continua), quindi al termine di essa imposti la DataSource della tabella con il DataTable appena generato.

L'infrastruttura per i Thread in C# è una goduria, e l'introduzione degli operatori await e async ha reso il tutto di una banalità unica (anche se è sempre meglio darsi una bella letta alla gestione delle operazioni asincrone prima dell'introduzione di questi operatori, per capire davvero come funziona il tutto).

Ciao, ti ringrazio per la risposta.
Così facendo però avrò la datagrid popolata solo alla fine del prelievo dati, mi sarebbe piaciuto un qualcosa di progressivo..

Inviato dal mio GT-N7100 con Tapatalk 4

totti240282
30-09-2013, 12:00
Anche se il vero Thread si fa senza quegli operatori, operazioni asincrone sono differenti da operazioni su altri Thread.

[Kendall]
30-09-2013, 12:50
Anche se il vero Thread si fa senza quegli operatori, operazioni asincrone sono differenti da operazioni su altri Thread.

Ni.

Non ho detto che gli operatori async e await SONO il multithreading, ma che l'introduzione degli stessi ha reso la gestione di più thread ancor più banale rispetto alla già semplificata struttura creata tramite i Task.

Il discorso poi è molto vasto e per nulla banale. Asincronia, Synchronization Context, generazione nuovi thread... Sono tutti argomenti che entrano in gioco, e appunto e tutto fuorchè banale.

rizzotti91
30-09-2013, 16:00
L'utilizzo della modalità virtuale della datagridview potrebbe essere una soluzione?
Come faccio a popolare una dataGridView in virtual mode a partire da un DB?

rizzotti91
30-09-2013, 17:07
Intanto sto facendo delle prove per far si che il thread per il caricamento della dataTable venga eseguito in background però, sinceramente, non so come muovermi...

Al momento, nel form con la dataGrid, ho il richiamo ad un metodo da me creato:

dataGrid.dataSource = CaricaDT(query, datatable);

Il metodo è così:
Thread thread = new Thread(() => SvolgiDT(query, dt));
thread.Start();
while (thread.IsAlive)
{

}
return dt;



dt.Clear();
try
{
Connection.Apri();
MySqlDataAdapter da = new MySqlDataAdapter(query, Connection.cnMySql);
da.Fill(dt);
Connection.Chiudi();
return dt;
}
catch (MySqlException)
{
MessageBox.Show("Errore!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}

Il problema è che non ci ho concluso nulla così... la GUI si blocca quando carico la datagrid..

Storti
30-09-2013, 19:05
L'utilizzo della modalità virtuale della datagridview potrebbe essere una soluzione?
Per velocizzare la visualizzazione dei dati sì. Per il caricamento dal DB ovviamente no.

Riordian
01-10-2013, 07:17
Se hai migliaia di record secondo me converrebbe comunque fare una paginazione della datagrid view... così facendo prelevi decisamente meno record da db diminuendo i tempi per visualizzare la pagina... io farei così ;) Comunqe il threading rimana una soluzione valida ovviamente.
Oltretutto anche per l'utente che visualizza i dati sarebbe meglio, poi dipende dalle esigenze della tua applicazione. ;)

Riordian
01-10-2013, 07:24
Se hai migliaia di record secondo me converrebbe comunque fare una paginazione della datagrid view... così facendo prelevi decisamente meno record da db diminuendo i tempi per visualizzare la pagina... io farei così ;) Comunqe il threading rimana una soluzione valida ovviamente.
Oltretutto anche per l'utente che visualizza i dati sarebbe meglio, poi dipende dalle esigenze della tua applicazione. ;)

altra soluzione potrebbe essere il caricamento durante lo scrolling dei dati successivi, un po' come succede nei social network.

rizzotti91
01-10-2013, 11:29
altra soluzione potrebbe essere il caricamento durante lo scrolling dei dati successivi, un po' come succede nei social network.

Infatti é proprio questo che vorrei fare... E da quello che ho capito, la virtual mode serve proprio a questo. Inoltre vorrei che il caricamento avvenga comunque in un Thread separato, in modo da non bloccare mai la GUI. Qualcuno mi sa indicare come fare?

Inviato dal mio GT-N7100 con Tapatalk 4

Riordian
01-10-2013, 13:05
sono un po' a digiuno di windows form mi spiace, l'unica cosa che ti suggeisco è, se hai cos' tanti dati da prelevare da DB, di evitare di farlo con un unico accesso. Indipendentemente dal'utilizzo del thread o meno ;)

marco.r
01-10-2013, 22:58
Consiglio anche io la paginazione.
Oggi sono 20.000 record, e se fra un anno sono 200.000 ? Lasci che il thread scarichi per 5 minuti intasando il DB ?
Aggiungo pure che
- piu' record sono piu' memoria occupano, e quindi il programma comunque rallentera'.
- se l'utente inoltre decide di riordinare l'elenco a meta' scaricamento l'effetto non e' piacevole
- una scrollbar per scorrere 20k e passa record e' praticamente inutile, a meno di non dotare tutti di monitor 80" in verticale.

Il riempimento progressivo mentre si scrolla non mi piace, non si capisce mai bene quanti dati ci sono e come navigarli. Va bene per i social network perche' comunque si tratta sempre e solo di dati ordinati temporalmente di cui ti importano solo gli eventi piu' recenti. Nessuno si mette a scrollare la pagina di facebook per pescare un post di due mesi fa...

La soluzione paginata non sara' molto "kool" ma secondo me la piu' efficace.

Riordian
02-10-2013, 18:52
Consiglio anche io la paginazione.
Oggi sono 20.000 record, e se fra un anno sono 200.000 ? Lasci che il thread scarichi per 5 minuti intasando il DB ?
Aggiungo pure che
- piu' record sono piu' memoria occupano, e quindi il programma comunque rallentera'.
- se l'utente inoltre decide di riordinare l'elenco a meta' scaricamento l'effetto non e' piacevole
- una scrollbar per scorrere 20k e passa record e' praticamente inutile, a meno di non dotare tutti di monitor 80" in verticale.

Il riempimento progressivo mentre si scrolla non mi piace, non si capisce mai bene quanti dati ci sono e come navigarli. Va bene per i social network perche' comunque si tratta sempre e solo di dati ordinati temporalmente di cui ti importano solo gli eventi piu' recenti. Nessuno si mette a scrollare la pagina di facebook per pescare un post di due mesi fa...

La soluzione paginata non sara' molto "kool" ma secondo me la piu' efficace.
Quoto tutto.. in effetti per una griglia la cosa migliore è la paginazione..

rizzotti91
02-10-2013, 21:14
Ok, è la cosa migliore, ma come si realizza?

marco.r
02-10-2013, 22:48
Stai usando windows forms ? (Non mi sembra che datagridview faccia parte di wpf, o no?)
Con C# per le gui ho usato solo silverlight per cui non ti posso dare un aiuto diretto con datagridview cmq l'idea di base e' questa:
una volta deciso il numero di record (N) da visualizzare alla volta, per visualizzare la pagina P devi prendere i record da (P-1)*N a P*N

Cpm SQL SERVER e' qualcosa tipo

SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY ??? ) AS RowNum, *
FROM MyTable
WHERE SOME_CONDITION
) AS Result
WHERE RowNum >= START_RECORD -- (P-1)*N
AND RowNum < END_RECORD -- P*N

Insomma non fai altro che mostrare un sottoset limitato di tutta la tabella
Avrai bisogno di qualche pulsante per gestire la navigazione (pagina successiva pagina precedente) che non fa altro che impostare il nuovo numero di pagina e aggiornare di nuovo il contenuto della datagrid in base al nuovo intervallo. Lavoro un po' noioso ma non difficile.

Forse c'e' qualcosa di gia' pronto per le windows forms, non so, cmq se cerchi datagridview pagination so google trovi diversi esempi gia' pronti.

Riordian
03-10-2013, 09:03
Prova a vedere, come diceva anche marco, se il controllo offre qualcosa di già pronto. Ai tempi un controllo simile che ho usato con asp.net, lo aveva, si settava qualche proprietà del controllo e avevi tutto praticamente gratis. Dubito che non l'abbiano fatto anche per windows form o l'abbiano levato.
In caso contrario ho trovato questo esempio... vedi se ti è utile ;) http://www.codeproject.com/Articles/211551/A-Simple-way-for-Paging-in-DataGridView-in-WinForm