2011-01-18 11 views
8

Mam aplikację przeglądarki bazy danych WPF: To proste okno główne zawierające kontrolę użytkownika z siatką danych pokazującą dane wyodrębnione z bazy danych SQLite.
Problem polega na tym, że uruchomienie tej aplikacji trwa 6 sekund, dopóki nie będzie można jej użyć.Poprawić postrzegany czas uruchamiania aplikacji WPF

próbowałem budować kontrolę użytkownika (i robi wszystko ładowanie danych) w konstruktorze okna głównego:
ekran powitalny zostanie pokazany 5s ten sposób, następnie przez 1s w pustym oknie głównym, aż aplikacja jest gotowy do użycia.
Użytkownicy powiedzieli, że trwa to zbyt długo, dopóki coś (wizualnie) się nie wydarzy.

Następnie przeniosłem tworzenie kontroli użytkownika (i ładowanie danych) do Załadowanego programu obsługi zdarzeń głównego okna: Ekran powitalny zostanie wyświetlony 3s, a następnie 3s pustego okna głównego, dopóki aplikacja nie będzie gotowa.
Użytkownicy stwierdzili, że jest "lepszy", ale nie podoba im się to, że w połowie gotowe okno główne jest wyświetlane w stanie wyłączonym przez tak długi czas.

Czy można znaleźć ogólne porady dotyczące spodziewanego czasu ładowania aplikacji lub czy istnieją inne zalecenia dotyczące poprawy tej sytuacji?
Uważam, że najlepiej byłoby, gdyby główne okno było wyświetlane tak szybko, jak to możliwe, wraz z klepsydrą lub spinner do momentu załadowania danych. Ale nie mogę po prostu przenieść kreacji kontroli użytkownika do tła działającego tak, jak w przypadku niewłaściwego wątku.

Czy ktoś ma jakieś sugestie dotyczące tego problemu?

Edytuj:
Zauważ, że w tej chwili właśnie przypisałem kwerendę LINQ-do-EF jako źródło danych siatki.
Możliwym poprawa może załadować te dane do tabeli danych w tle i przypisać ją tylko raz załadowany ...

Edit2: Używam .NET 4 z System.Data.SQLite i EF4 załadować dane. Istnieje mniej więcej 4000 wierszy i 30 kolumn.

+0

Ile danych ładujesz z bazy danych? W jaki sposób ładujesz dane - używając ORM (jeśli tak, które?) Lub zwykłego ADO.NET? – alimbada

+0

Ucz się użytkowników, że dużo się dzieje. Sprawdź, co naprawdę się dzieje i odpowiednio zoptymalizuj. Loginscreen lub rozszerzony splash (z pewną falistą animacją/progiem) może być dokładnie tym, czego szukają. – CodingBarfield

+0

@alimbada: Edytowałem pytanie, aby uwzględnić te informacje. Ale jest to raczej ogólne pytanie niż związane z Entity Framework, itp. ADO.NET lub jakakolwiek ORM potrzebuje czasu, aby załadować dane, możesz również zastąpić to Thread.leep (..). Pytanie brzmi raczej jak poradzić sobie z taką sytuacją. – Marc

Odpowiedz

13

Załaduj dane asynchronicznie. Przedstaw coś fajnego na GUI dla użytkownika podczas ładowania. Poniższy kod może ci w tym pomóc:

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

Aplikacja nie jest szybsza, ale wydaje się być o wiele szybciej, ponieważ GUI jest natychmiast widoczne i elastyczne. Może Ty też możesz pokazać użytkownikowi część wczytanych danych podczas ładowania reszty. Aby to zrobić, użyj ProgressChanged.

Aktualizacja

Nie jestem pewien, czy rozumiem problemu rację. Jeśli Twoim problemem nie jest załadowanie danych dotyczących czasu, w aplikacji jest coś dziwnego. WPF jest IMO bardzo szybko. Tworzenie kontroli nie zajmuje dużo czasu. Wizualizuję znacznie większe listy, o których wspominasz w ciągu kilku milisekund.

Spróbuj sprawdzić, czy w interfejsie użytkownika znajduje się coś, co utrudnia firmie DataGrid wirtualizację elementów. Może masz tam proplem. Aby analizować aplikacje WPF, mogę polecić Ci WPF Profiling Tools.

+0

Również tak robi Silverlight. (Inna składnia, ta sama zasada). –

+0

Tak, tak jak do tej pory operowałem wolnymi operacjami i działało całkiem nieźle. Jedynym problemem jest to, że przed wywołaniem bgWorker.RunWorkerAsync() musisz wyłączyć interfejs użytkownika, ponieważ może to zmylić użytkownika. – Marc

+1

@Marc: Tak, ale możliwe, że możesz wyłączyć tylko niektóre części interfejsu, co jest miłym doświadczeniem dla użytkownika. Jak już napisałem, jeśli dane ładnie się mieszczą, możesz także przedstawić pierwsze kilka załadowanych rekordów lub plików i pozwolić użytkownikowi już z nimi pracować. Ale jasne jest, że wszystkie te fajne rzeczy kosztują czas opracowywania i sprawiają, że rzeczy są bardziej złożone.Pytanie brzmi, czy klient za to zapłaci i czy ma sens złożenie projektu złożonego ... – HCL

2

Najbardziej oczywistą rzeczą, jaką można zrobić, to profilować aplikację i znaleźć wąskie gardła w czasie uruchamiania. Wygląda na to, że najbardziej prawdopodobnym winowajcą będzie ładowanie danych z bazy danych.

Jedną z lekcji, której nauczyłem się, jest to, że jeśli korzystasz z ORM, podczas ładowania dużych zbiorów danych, jeśli preferujesz POCO (Zwykłe stare obiekty CLR/C#) przez ORM-owe jednostki bazy danych (patrz przykład poniżej), obciążenie czas będzie o wiele szybszy, a zużycie pamięci RAM również ulegnie znacznemu zmniejszeniu. Powodem tego jest to, że EF spróbuje załadować cały podmiot (tj. Wszystkie jego pola) i ewentualnie cały ładunek danych związanych z twoimi jednostkami, z których większość nie będzie nawet potrzebna. Jedynym czasem, w którym naprawdę potrzebujesz bezpośrednio pracować z jednostkami, jest operacja wstawiania/aktualizacji/usuwania. Podczas odczytu danych powinieneś uzyskać tylko pola, które Twoja aplikacja musi wyświetlić i/lub sprawdzić.

Jeśli zastosujesz wzór MVVM, powyższa architektura nie będzie trudna do wdrożenia.

Przykład ładowania danych do Poços EF:

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

return query.ToList(); 

Poços są bardzo proste zajęcia z autoproperties dla każdego pola.

Zwykle posiadamy repozytoria dla każdej jednostki w naszych aplikacjach, a każde repozytorium jest odpowiedzialne za pobieranie/aktualizację danych dotyczących tej jednostki. Modele widoku mają odniesienia do repozytoriów, których potrzebują, więc nie używają EF bezpośrednio. Kiedy użytkownicy wprowadzają zmiany, które wymagają utrwalenia, używamy w repozytorium innych metod, które następnie ładują tylko podzbiór encji (tj. Te, które użytkownik zmienił) i stosują niezbędne aktualizacje - z pewną weryfikacją wykonaną przez viewmodel i ewentualnie inną walidacją dzieje się w DB przez ograniczenia/wyzwalacze, itp.

+0

+1 za Twoje rekomendacje. Zrobiłem profil aplikacji. To naprawdę mniej więcej inicjacja aplikacji (i framework) 3s, której nie będę mógł poprawić. Pozostałe 3s pochodzą z tworzenia kontroli użytkownika i ładowania danych. Myślałem także o używaniu podstawowych czytników danych ADO.NET, aby poprawić wydajność. – Marc

+0

Czy masz jakieś dobre linki do przykładów MVVM, które pokazują, jak radzą sobie z ładowaniem danych w tle? Co oni robią z widokiem podczas ładowania? – Marc

+0

Niestety, nie mam pod ręką żadnych przykładów online; to głównie rzeczy, których nauczyłem się od kolegi. Dodałem własny przykład i opracowałem trochę na temat mojej oryginalnej odpowiedzi. Mogę osobiście ręczyć za to, że działa, ponieważ aplikacja, nad którą obecnie pracujemy, zajęła ponad półtorej minuty. Teraz jest mniej niż 10 sekund. Robimy od 300 do 400 000 odczytów z SQL Server DB podczas uruchamiania ... – alimbada

0

Istnieje wiele powodów tego.

1) Wdrożenie może mieć dość niską konfigurację.
2) Właściwy lub problem z powiązaniem danych.

Możliwe rozwiązania to:
1) Sztuczna ładunek danych
2) optymalizować wydajność. http://msdn.microsoft.com/en-us/library/aa970683.aspx

Widziałem aplikacje renderują rekordy 5M mniej niż sekundę w wpf.

PS: Kolejnym możliwym powodem może być 30 kolumn, z powodu dostępu do kolejności kolumn.

Powiązane problemy