2011-01-18 10 views
8

Ho un'applicazione di visualizzazione del database WPF: è una semplice finestra principale contenente un controllo utente con una griglia di dati che mostra i dati estratti da un database SQLite.
Il problema è che questa applicazione impiega 6 secondi per essere avviata fino a quando non è utilizzabile.Miglior tempo di avvio dell'app WPF percepito

Ho provato costruire il controllo utente (e facendo tutto il caricamento dei dati) nel costruttore della finestra principale:
La schermata iniziale verrà mostrato 5s questo modo, poi seguita da 1s di finestra principale vuoto finché l'applicazione è pronto per essere usato
Gli utenti hanno detto che ci vuole troppo tempo prima che qualcosa (visivamente) accada.

Ho quindi spostato la creazione del controllo utente (e il caricamento dei dati) nel gestore eventi Loaded della finestra principale: La schermata iniziale verrà mostrata 3s, seguita da 3s della finestra principale vuota finché l'applicazione non sarà pronta.
Gli utenti hanno detto che è "migliore", ma non mi piace il fatto che una finestra principale finita è mostrata in stato disabilitato per così tanto tempo.

Esiste qualche consiglio generale sul tempo di caricamento dell'applicazione percepito o ci sono altre raccomandazioni su come migliorare questa situazione?
Credo che idealmente la finestra principale sarebbe mostrata il più velocemente possibile, insieme a qualche ora di vetro o spinner fino al caricamento dei dati. Ma poi non posso semplicemente spostare la creazione del controllo utente in un worker in background, in quanto ciò avverrebbe nel thread sbagliato.

Qualcuno ha qualche suggerimento su questo problema?

Edit:
Nota che in questo momento ho appena assegnato una query LINQ to EF come origine dati griglia.
Una possibile miglioramento può essere quello di caricare questi dati in una tabella di dati in background e assegnarlo solo una volta caricato ...

Edit2: sto usando .net 4 con System.Data.SQLite e EF4 per caricare i dati. Ci sono più o meno 4000 righe e 30 colonne.

+0

Quanti dati si stanno caricando dal database? Come stai caricando i dati - usando un ORM (se sì, quale?) O semplicemente ADO.NET? – alimbada

+0

Informa gli utenti che sta succedendo molto. Scopri cosa sta realmente accadendo e ottimizza di conseguenza. Un loginscreen o splash esteso (con qualche animazione/progressbar ondulata) potrebbe essere esattamente quello che stanno cercando. – CodingBarfield

+0

@alimbada: ho modificato la domanda per includere queste informazioni. Ma è più una questione generale che legata a Entity Framework, ecc. ADO.NET o qualsiasi ORM impiegherà il suo tempo per caricare i dati, potresti anche sostituirlo con Thread.Sleep (..). La domanda è più su come affrontare questo tipo di situazione. – Marc

risposta

13

Carica dati asincroni. Presentare qualcosa di carino sulla GUI per l'utente durante il caricamento. Il seguente codice può aiutare con questo:

BackgroundWorker bgWorker = new BackgroundWorker() { WorkerReportsProgress=true}; 
bgWorker.DoWork += (s, e) => {  
    // Load here your file/s  
    // Use bgWorker.ReportProgress(); to report the current progress 
}; 
bgWorker.ProgressChanged+=(s,e)=>{  
    // Here you will be informed about progress and here it is save to change/show progress. 
    // You can access from here savely a ProgressBars or another control. 
}; 
bgWorker.RunWorkerCompleted += (s, e) => {  
// Here you will be informed if the job is done. 
// Use this event to unlock your gui 
}; 
bgWorker.RunWorkerAsync(); 

L'applicazione non è più veloce, ma sembra essere molto più veloce perché l'interfaccia grafica è immediatamente visibile e reattivo. Forse puoi anche mostrare all'utente una parte dei dati caricati mentre carichi il resto. Utilizzare lo ProgressChanged -event per fare ciò.

Aggiornamento

Io non sono sicuro se ho ben capito il problema destra. Se il tuo problema non è il tempo necessario per caricare i dati, allora qualcosa è strano nella tua applicazione. WPF è IMO molto veloce. La creazione del controllo non richiede molto tempo. Visualizzo elenchi molto più grandi come si menziona in alcuni millisecondi.

Prova a cercare se nella tua interfaccia utente c'è qualcosa che impedisce a DataGrid di virtualizzare gli elementi. Forse hai un programma lì. Per analizzare le app WPF, posso consigliarti lo WPF Profiling Tools.

+0

Inoltre, questo è il modo in cui Silverlight lo fa. (Diversa sintassi, lo stesso principio.) –

+0

Sì, è così che ho gestito le operazioni lente fino ad ora e ha funzionato abbastanza bene. L'unico problema è che prima di chiamare bgWorker.RunWorkerAsync() devi disabilitare l'interfaccia utente altrimenti potrebbe confondere l'utente. – Marc

+1

@Marc: Sì, tuttavia forse è possibile disabilitare solo alcune parti dell'interfaccia utente, che è una bella esperienza per l'utente. Come ho scritto, se i dati si nascondono bene, puoi anche presentare i primi pochi record o file caricati e lasciare che l'utente lavori già con loro. Ma è chiaro, tutte queste belle cose costano tempo di sviluppo e rendono le cose più complesse.La domanda è, se il cliente pagherà per esso e se ha senso incerementare la complessità del progetto ... – HCL

2

La cosa più ovvia che puoi fare è profilare l'applicazione e trovare i colli di bottiglia in fase di avvio. Sembra che il colpevole più probabile sarà il caricamento dei dati dal tuo database.

Una lezione che ho imparato è che se si sta utilizzando un ORM, quando si caricano set di dati di grandi dimensioni se si preferisce POCO (Plain Old CLR/C# Objects) su entità di database generate da ORM (vedere esempio di seguito), il carico il tempo sarà molto più veloce e anche l'utilizzo della RAM sarà notevolmente ridotto. La ragione di ciò è che EF proverà a caricare l'intera entità (cioè tutti i suoi campi) e probabilmente un intero carico di dati relativi alle tue entità, molte delle quali non ti serviranno nemmeno. L'unica volta in cui hai davvero bisogno di lavorare direttamente con le entità è quando esegui operazioni di inserimento/aggiornamento/cancellazione. Durante la lettura dei dati è necessario solo ottenere i campi che l'applicazione deve visualizzare e/o convalidare.

Se si segue il modello MVVM, l'architettura di cui sopra non è difficile da implementare.

Esempio di caricamento dei dati in POCOS con EF:

var query = from entity in context.Entities 
       select new EntityPoco 
       { 
        ID = entity.ID, 
        Name = entity.Name 
       }; 

return query.ToList(); 

POCOS sono classi molto semplici con autoproperties per ciascun campo.

Generalmente nelle nostre applicazioni sono presenti repository per ogni entità e ciascun repository è responsabile dell'ottenere/aggiornare i dati relativi a tale entità. I modelli di vista hanno riferimenti ai repository di cui hanno bisogno in modo che non utilizzino direttamente EF. Quando gli utenti apportano modifiche che devono essere persistenti, vengono utilizzati altri metodi nel repository che quindi caricano solo un sottoinsieme di entità (ovvero quelle modificate dall'utente) e applicano gli aggiornamenti necessari - con alcune convalide eseguite da viewmodel ed eventualmente altre convalide andando avanti nel DB tramite vincoli/trigger, ecc.

+0

+1 per i tuoi consigli. Ho fatto il profilo dell'applicazione. È un'inizializzazione di app (e framework) molto più o meno 3s che non potrò migliorare. Gli altri 3 provengono dalla creazione del controllo utente e dal caricamento dei dati. Ho anche pensato di utilizzare i lettori di dati ADO.NET di base per migliorare le prestazioni. – Marc

+0

Hai dei buoni collegamenti agli esempi MVVM che mostrano come gestiscono il caricamento dei dati in background? Cosa stanno facendo con la vista durante il caricamento? – Marc

+0

Siamo spiacenti, non ho nessun esempio online disponibile; è principalmente roba che ho imparato da un collega. Ho aggiunto il mio esempio e ho elaborato un po 'la mia risposta originale. Posso garantire personalmente che funzioni, perché l'applicazione a cui stiamo lavorando in origine ha richiesto più di un minuto e mezzo per essere caricata. Ora è a meno di 10 secondi. Stiamo facendo tra 300k e 400k letture da un DB di SQL Server all'avvio ... – alimbada

0

Ci sono molte ragioni per questo.

1) La macchina di distribuzione potrebbe avere una configurazione piuttosto bassa.
2) In-corretto o problema con l'associazione dei dati.

Possibili soluzioni sarebbero:
1) pigro caricare i dati
2) ottimizzare le prestazioni. http://msdn.microsoft.com/en-us/library/aa970683.aspx

Ho visto applicazioni che rendono i record 5M meno di un secondo in wpf.

PS: un ulteriore motivo può essere 30 colonne, a causa dell'accesso all'ordine delle colonne.

Problemi correlati