2011-01-18 36 views
8

Tengo una aplicación de visor de base de datos WPF: Es una ventana principal simple que contiene un control de usuario con una cuadrícula de datos que muestra los datos extraídos de una base de datos SQLite.
El problema es que esta aplicación tarda 6 segundos en iniciarse hasta que se pueda utilizar.Mejorar el tiempo percibido de inicio de la aplicación WPF

Intenté construir el control de usuario (y haciendo toda la carga de datos) en el constructor de la ventana principal:
La pantalla de bienvenida se mostrará 5s esta manera, a continuación, seguido por 1s de ventana principal de vacío hasta que la aplicación es listo para ser usado.
Los usuarios dijeron que tarda demasiado hasta que sucede algo (visualmente).

Luego moví la creación del control de usuario (y la carga de datos) al controlador de eventos cargado de la ventana principal: La pantalla de inicio mostrará 3s, seguido de 3s de ventana principal vacía hasta que la aplicación esté lista.
Los usuarios dijeron que es "mejor", pero no les gusta el hecho de que una ventana principal a medio terminar se muestre en estado desactivado durante tanto tiempo.

¿Hay algún consejo general sobre el tiempo de carga de aplicación percibido o hay alguna otra recomendación sobre cómo se puede mejorar esta situación?
Creo que lo ideal sería que la ventana principal se muestre lo más rápido posible, junto con un reloj de arena o una ruleta hasta que se carguen los datos. Pero entonces no puedo simplemente mover la creación de control de usuario a un trabajador de segundo plano ya que esto se haría con el hilo equivocado.

¿Alguien tiene alguna sugerencia para este problema?

Edit:
Tenga en cuenta que en este momento acabo de asignar una consulta LINQ-to-EF como el origen de datos de la cuadrícula.
Una posible mejora puede ser para cargar estos datos en una tabla de datos en segundo plano y asignar sólo una vez cargado ...

Edit2: estoy usando .NET 4 con System.Data.SQLite y EF4 para cargar los datos. Hay más o menos 4000 filas y 30 columnas.

+0

¿Cuántos datos está cargando de la base de datos? ¿Cómo está cargando los datos? ¿Utiliza un ORM (si es así, cuál?) O simplemente ADO.NET? – alimbada

+0

Eduque a los usuarios que están sucediendo muchas cosas. Verifique lo que realmente está sucediendo y optimícelo según corresponda. Una pantalla de inicio de sesión, o salpicadura extendida (con alguna animación ondulada/barra de progreso) podría ser exactamente lo que están buscando. – CodingBarfield

+0

@alimbada: He editado la pregunta para incluir esta información. Pero es más una cuestión general que vinculada a Entity Framework, etc. ADO.NET o cualquier ORM se tomará su tiempo para cargar los datos, también puede reemplazar esto con Thread.Sleep (..). La pregunta es más sobre cómo lidiar con este tipo de situación. – Marc

Respuesta

13

Cargue sus datos de forma asíncrona. Presente algo agradable en la GUI para el usuario durante la carga. El siguiente código puede ayudar con esto:

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(); 

La aplicación no es más rápido, pero parece ser mucho más rápido debido a que la interfaz gráfica de usuario es inmediatamente visible y sensible. Quizás también pueda mostrar al usuario una parte de los datos cargados mientras carga el resto. Use el ProgressChanged -ventivo para hacer esto.

actualización

No estoy seguro si entiendo su problema derecha. Si su problema no es el tiempo que necesita cargarse los datos, entonces algo es extraño en su aplicación. WPF es IMO muy rápido. La creación de control no toma mucho tiempo. Visualizo listas mucho más grandes como mencionas en algunos milisegundos.

Intenta ver si tienes algo en tu UI que impida que DataGrid virtualice los elementos. Quizás tengas un proplem allí. Para analizar las aplicaciones de WPF, puedo recomendarle el WPF Profiling Tools.

+0

Además, así es como lo hace Silverlight. (Sintaxis diferente, el mismo principio.) –

+0

Sí, así es como manejé las operaciones lentas hasta ahora y funcionó bastante bien. El único problema es que antes de llamar a bgWorker.RunWorkerAsync() tiene que deshabilitar la UI ya que de lo contrario puede confundir al usuario. – Marc

+1

@Marc: Sí, sin embargo, quizás pueda desactivar solo algunas partes de la IU, es una experiencia agradable para el usuario. Como escribí, si los datos están bien, también puede presentar los primeros registros o archivos cargados y dejar que el usuario ya trabaje con ellos. Pero está claro, todas estas cosas agradables cuestan tiempo de desarrollo y hacen las cosas más complejas.La pregunta es si el cliente pagará por ella y si tiene sentido implantar la complejidad del proyecto ... – HCL

2

Lo más obvio que puede hacer es perfilar su aplicación y encontrar los cuellos de botella en el tiempo de arranque. Parece que el culpable más probable será la carga de datos de su base de datos.

Una lección que aprendí es que si está utilizando un ORM, cuando cargue conjuntos de datos grandes si prefiere POCO (objetos CLR/C# simples) en entidades de base de datos generadas ORM (consulte el ejemplo a continuación), la carga el tiempo será mucho más rápido y el uso de RAM también se reducirá significativamente. La razón para esto es que EF intentará cargar la entidad completa (es decir, todos sus campos) y posiblemente una gran cantidad de datos relacionados con sus entidades, la mayoría de los cuales ni siquiera necesitará. La única vez que realmente necesita trabajar directamente con las entidades es cuando realiza operaciones de inserción/actualización/eliminación. Al leer datos, debe solo obtener los campos que su aplicación necesita para mostrar y/o validar.

Si sigue el patrón MVVM, la arquitectura anterior no es difícil de implementar.

Ejemplo de carga de datos en POCOs con EF:

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

return query.ToList(); 

POCOs son clases muy simples con autoproperties para cada campo.

Normalmente tenemos repositorios para cada entidad en nuestras aplicaciones y cada repositorio es responsable de obtener/actualizar los datos relacionados con esa entidad. Los modelos de vista tienen referencias a los repositorios que necesitan para que no usen EF directamente. Cuando los usuarios realizan cambios que deben persistir, usamos otros métodos en el repositorio que luego solo cargan un subconjunto de entidades (es decir, las que el usuario cambió) y aplicamos las actualizaciones necesarias, con alguna validación hecha por el modelo de vista y posiblemente otra validación pasando por DB a través de restricciones/activadores, etc.

+0

+1 para sus recomendaciones. Hice un perfil de la aplicación. Realmente es más o menos la inicialización de la aplicación (y el marco) que no podré mejorar. Los otros 3 provienen de la creación del control de usuario y la carga de datos. También pensé en usar lectores de datos ADO.NET básicos para mejorar el rendimiento. – Marc

+0

¿Tiene buenos enlaces a ejemplos de MVVM que muestran cómo manejan la carga de datos en segundo plano? ¿Qué están haciendo con la vista durante la carga? – Marc

+0

Lo siento, no tengo ningún ejemplo en línea a la mano; es principalmente cosas que aprendí de un colega. Agregué mi propio ejemplo y elaboré un poco sobre mi respuesta original. Personalmente puedo responder que funciona, porque la aplicación en la que estamos trabajando originalmente tomó más de un minuto y medio para cargar. Ahora ha bajado a menos de 10 segundos. Estamos haciendo lecturas entre 300k y 400k desde un DB de SQL Server al inicio ... – alimbada

0

Hay muchas razones para esto.

1) La máquina de implementación puede tener una configuración bastante baja.
2) Correcto o problema con el enlace de datos.

Posibles soluciones serían:
1) Lazy cargar los datos
2) optimizar el rendimiento. http://msdn.microsoft.com/en-us/library/aa970683.aspx

Tenía aplicaciones de sierra renderizar 5M graba menos de un segundo en wpf.

PD: Otra razón mínima posible puede ser 30 columnas, debido al acceso de orden de columnas.

Cuestiones relacionadas