Laden...

Lange Ladezeiten vermeiden?

Erstellt von Voidcore vor 14 Jahren Letzter Beitrag vor 14 Jahren 4.471 Views
V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren
Lange Ladezeiten vermeiden?

verwendetes Datenbanksystem: FireBird embedded

Hallo,

ich habe ein problem das die zugriffe immer 1-2 sekunden dauern und dadurch meine GUI kurz hängt.

Gibt es eine Möglichkeit zb. die Datenbank vorher einlesen (cachen) oder anderes?

Wenn ich für jede Abfrage ein Threead machen wird das ganze sehr unübersichtlicht.

Danke

Gelöschter Account
vor 14 Jahren

wie wäre es denn wenn du die gui im allgemeinen von der BL trennst?

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Habe schon alles gebunden, jede Comobox, jedes Datagridview alles via bindung.

Ich Update jeweils nur des DataTable . jedoch von der GUI aus 😕

Um zb. query zu erstellen greife ich auf die gui zu (textbox.text oder combobox.text)

Irgendwie ist schon "wenig" mit der gui gemacht ... aber gibt anscheint noch viel mehr Möglichkeiten 😕

Gelöschter Account
vor 14 Jahren

gebunden bedeutet nur, das du dir schreibarbeit sparst. deswegen passiert immer noch alles im gui-thread. binding verhindert aber nicht, das man die gui von logischen elementen entkoppelt. du musst zunächst sämtliche zugriffe auf die datenbank durch einen kanal bündeln. dann kannst du eben diesen kanal in einen anderen thread entkoppeln und beseitigst somit dein problem.

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

JAck30lena,

kennst du irgendwo eine kleine tutorial wo man sich ein wenig einlesen kann. ich als Hobby Programmierer habe da nicht so viel Erfahrung.

Ich weiß was threads sind usw.. jedoch tue ich mich bei der Benutzung noch recht schwer.

danke im voraus

1.564 Beiträge seit 2007
vor 14 Jahren

Hallo Voidcore

Die Haupt-Schwierigkeit bei deinem Anliegen ist die Frage ob und wie die Applikation überhaupt in der Lage ist vorausschauend zu wissen welche Daten als nächstes benötigt werden. Ist diese Frage für dich geklärt?

Was JAck30lena meint ist deine ganzen Abfragen und Datenbankzugriffe in eine Business-Schicht (Business-Layer) zu kapseln. Du verwendest also keine Connections mehr irgendwo innerhalb der GUI sondern einen Business-Context welcher die Datenbankzugriffe kapselt. Hast du die Kapselung mal erreicht ist es nicht mehr so schwierig die gesamten Aktionen zu parallelisieren. Beispiele zu Business-Layern gibt's im Web wahrscheinlich viele - ich habe jetzt aber keinen Link zur Hand.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

K
593 Beiträge seit 2007
vor 14 Jahren

Hallo Leute,

ich glaube bei voidcore ist das Problem prinzipiel einfacher noch. Natürlich ist aber ein BL immer schön 😃 Ich denke du bindest direkt an die Datenbank so dass bei jeder combobox etc Daten von der datenbank geholt und aktualisiert werden? Klingt jedenfalls so, dann solltest du "zwischen" Objekte nutzen, erstmal alles reinladen was du brauchst und erst wenn der Benutzer etwas ändert oder neue daten benötigt die daten zu holen/ändern.

Viele Grüße

Kaji

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Es geht in meinem Fall nur um das auslesen der Daten ich will nicht einmal was ändern.

Nur darstellen. Jedoch "blockiert" die Anwendung sobald ich einen anderen Datensatz lese.

Ich möchte aber nicht alles mit 1000 Threads machen um das blockieren zu verhintern.

3.430 Beiträge seit 2007
vor 14 Jahren

Hallo voidcore,

wieso 1000 Threads?
Wenn man das Programm richtig aufbaut dann reicht im Optimalfall schon ein Thread der die ganze Arbeit übernimmt und halt noch der GUI-Thread.

Du musst einfach das Ganze soweit wie möglich entkoppeln

GUI -> Starte Thread -> Daten auslesen -> Status an die GUI senden

Was du dabei alles beachten musst und wie man es macht findest du hier:
[FAQ] Warum blockiert mein GUI?

Gruss
Michael

115 Beiträge seit 2008
vor 14 Jahren

Hallo Voidcore,

das hatte ich mal gefunden und als recht gut empfunden:

ThreadingDotNet

Insgesamt git es 5 Teile...

kennst du irgendwo eine kleine tutorial wo man sich ein wenig einlesen kann. ich als Hobby Programmierer habe da nicht so viel Erfahrung.

Ich weiß was threads sind usw.. jedoch tue ich mich bei der Benutzung noch recht schwer.

danke im voraus

Grüße,
der Michael

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Danke für die Infos, Also muss ich viel viel zum Thema Threads lesen 😃

3.825 Beiträge seit 2006
vor 14 Jahren

1 - 2 Sekunden finde ich recht viel, auch wenn alles in einem Thread stattfindet.

Wieviele Tausend Datensätze liest Du denn ?

Liegt die Datenbank auf einem lokalen Laufwerk ?

Grüße Bernd

PS.: Mit Threads wird Deine Applikation auch nicht schneller. Aber wenn Du Glück hast sieht sie schneller aus 😉

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Die Datenbank hat schon 5k+ einträge und wird wöchentlich mehr.

Angezeigt werden meist so 200-300 Datensätze.

Die Datenbank liegt lokal (embedded Firebird)

Das meiste läuft folgende ab:


		// Update DataGridView
		void UpdateDGVRanking()
		{
			if (toolStripComboBoxDatum.Text == "")
				return;
			FbCommand cmd = new FbCommand(@"SELECT (0), id,ranking,rankingt, (' ') FROM FleetDataNG where added = @ADDED AND fleet = @FLEET AND ranking > 0 order by ranking asc;");
			cmd.Parameters.AddWithValue("@FLEET",comboBoxFleetRank.Text);
			cmd.Parameters.AddWithValue("@ADDED",toolStripComboBoxDatum.Text);
			SQLGetTable(cmd, ds.Tables["dtRanking"]);  // DataTable aktualisieren
			// Spalte Nummerieren
			for (int i = 1; i <= ds.Tables["dtRanking"].Rows.Count; i++)
				ds.Tables["dtRanking"].Rows[i -1][0] = i;
		}


		// Updaten der DataTables
		public void SQLGetTable(FbCommand command, DataTable Table)
		{
			try
			{
				using (FbConnection C = new FbConnection(fbConnectionString))
				{
					C.Open();
					command.Connection = C;
					FbDataAdapter FbDA = new FbDataAdapter(command);
					Table.Clear();
					FbDA.Fill(Table);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message.ToString());
			}
		}

alles im GUI Thread 😕

3.511 Beiträge seit 2005
vor 14 Jahren

Hallo,

das so eine kurze Abfrage 1-2 Sekunden dauert, deutet an sich auf einen fehlenden Index hin. Und 5k+ Einträge sind nicht wirklich viel. Das ist ein Tropfen auffen heißen Stein.

Was aber an dem Code sofort auffällt ist, das es keine Trennung zwischen GUI und Daten gibt. D.h. du rufst die Daten mitten in der GUI ab. Das muss auf jeden Fall getrennt stattfinden (was es auch später wesentlich einfacher macht, das ganze als separaten Thread auszulagern).

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

Gelöschter Account
vor 14 Jahren

1-2 sekunden für 5k datensätze sind auch dann lange, wenn der datenbankserver in der antarktis steht und du nur über china darauf zugreifen musst.

bei 5 millionen datensätzen hätte ich es verstanden oder wenn es eine komplexe abfrage mit 40 joins und x bedingungen wäre. da liegt irgendwo ein fehler.

generell gehört deine "ein-schicht architektur" überarbeitet. schau dich mal im netzt nach Drei-Schichten-Architektur um. Dein anwendungstyp ist für diese art der architektur gut geeignet.

3.511 Beiträge seit 2005
vor 14 Jahren

1-2 sekunden für 5k datensätze sind auch dann lange, wenn der datenbankserver in der antarktis steht und du nur über china darauf zugreifen musst.

Was aber hier nicht der Fall ist 😁

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Ich habe mir ein wenig die 3 Schicht Sachen angeschaut.

Vieles wird in extra klassen ausgelagert und getrennt, aber hilft das mir bei dem eigentlichen Problem?
Da doch auch die Schichten in meiner GUI laufen?

Gelöschter Account
vor 14 Jahren

Vieles wird in extra klassen ausgelagert und getrennt, aber hilft das mir bei dem eigentlichen Problem?

ja, es ist der erste schritt zur lösung. indem du die funktionalität trennst und nur noch wenige und definierte schnittpunkte hast, kannst du die aufrufe aus der gui durch threading entkoppeln.

weiterführendes:
[Artikel] Multi-Threaded Programmierung

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Angenommen ich lege mir eine klasse an welche alle datenbank zugriffe erledigt.

diese daten in der klasse hinterlegt woher weiß meine gui wann die daten bereit stehen?
Gibt es dafür schon lösungen? oder gebe ich einfach einen wert zurück welchen ich dan auswerte?

Sorry fuer die "anfänger" fragen, aber ich merke das dass was ich bisher gemacht habe sehr simple war und möchte mich nun damit auseinander setzen.

Als leihen nicht einfach 😮

5.299 Beiträge seit 2008
vor 14 Jahren

Jetzt mal ganz unabhängig von der Schichten/Threading-Diskussion:

Manchmal bremst man sich auch im Gui aus, wenn zufügen/ändern von Rows events auslöst, die aufwändig verarbeitet werden.

Du kannst mal eine Abfrage ohne Gui absetzen und gucken, ob das schneller geht.
Dann hastene Vorstellung, obs was mit der DB ist (fehlender Index, oder was), oder ob dein Gui zu optimieren wäre.

Im Gui hat man z.B. die Möglichkeit, BindingSource.RaiseEvents=false zu setzen, und nachm laden wieder auf True.
Dann muß man aber noch BindingSource.ResetBindings hinterherschieben, sonst bekommt die BS gar nichts mit von der neuen Datenlage.

Aber erstmal gucken, wos klemmt.

Der frühe Apfel fängt den Wurm.

3.430 Beiträge seit 2007
vor 14 Jahren

Hallo Voidcore,

guck dir mal das Tutorial von egrath an (hat Jack30Lena schon gepostet).
Punkt 5.2 wird genau beschrieben wie man bei der GUI mit Threads arbeitet.

Wenn du dein Auslesen aus der Klasse machst dann würde ich da ein Event hinzufügen auf welches die GUI reagieren kann und dann einfach die neuen Daten aus der Klasse holt.
Aber du musst dabei beachten dass du nicht vom Worker-Thread aus auf die Daten des GUI-Threads zugreifen darfst das es sonst zu Speicherinkonsistenzen kommt.
Deshalb musst du das .Invoke verwenden damit du aus dem Thread auf die GUI zugreifen kannst und damit es keine Probleme gibt.
Aber genaueres gibts hier: [FAQ] Warum blockiert mein GUI? und in dem genannten Tutorial

Gruss
Michael

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Ich habe keinen Index in meiner selbst erstellen Datenbank. Ich habe nur eine Unique Spalte um doppelte Einträge zu verhindern.

Auf welche Spalte(n) sollte man einen index legen? Wo macht es sinn und wo nicht?

Die meisten SQL Abfragen beinhalten host,server,id,fleet,added .. jedoch weiß ich nicht ob es sinn macht alle in den index zu nehmen.

V
Voidcore Themenstarter:in
106 Beiträge seit 2007
vor 14 Jahren

Habe einen Index auf Fleet, und added gelegt, und es wurde schneller 😃

Dennoch werde ich mir das mit den Schichten anschauen, und wenn ich nur eine Class machen für die datenbank zugriffe 😮

Danke an alle.