Laden...

[Label] viele erstellen = langsam

Erstellt von Frokuss vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.008 Views
F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren
[Label] viele erstellen = langsam

Guten Abend,

ich schreibe grade eine kleine Chatanwendung und bin grade dabei, die Chatdaten aus einer Datei in ein Fenster zu integrieren. Dabei werden etwa 150 Nachrichten geladen und in den Chat gepackt. Dabei ist aber das laden der Daten schon abgeschlossen, bevor die Label erstellt werden.

Nur die Label anzuzeigen, dauert bei mir etwa 6 Sekunden, was mir dann doch etwas hoch vorkommt. Daher komme ich grade ein wenig ins grübel, ob das ganze mit Label zu realisieren überhaupt das richtige ist... Bzw. ob ich nicht etwas gravierend falsch mache... Ich poste euch einfach mal etwas Code:

		private void ReadData2Chat(int id){//int chatId (Es gib mehrere Chats)
			Control cont = FindControl(this, "ChatVerlauf" + id);
			
			foreach(long t in chatKomplett[id].time){
				int i = chatKomplett[id].time.IndexOf(t);
				
				Label lab = LabelMessageUAndMe(id, chatKomplett[id].from2[i], chatKomplett[id].txt[i]);
				cont.Controls.Add(lab);
			}
			Panel pan = (Panel)cont;
			pan.VerticalScroll.Value = pan.VerticalScroll.Maximum;
		}

		private Label LabelMessageUAndMe(int id, int from, string txt){
			DateTime dt = DateTime.Now;//Nur für Testzwecke
			
			Control cont;
			if(from == thisUser.id)
				cont = FindControl(this, "ChatVerlauf" + id);
			else
				cont = FindControl(this, "ChatVerlauf" + from);
			Label lab = new Label();
			lab.MaximumSize = new Size(cont.Width, 0);
			lab.AutoSize = true;
			lab.Left = 10;
			
			if(from.Equals(thisUser.id)){
				lab.Text = "Ich: " + txt;
				lab.BackColor = MyForm_Set.ColorMe;//Ist static
			}
			else{
				lab.Text = "Du: " + txt;
				//lab.BackColor = MyForm_Set.ColorU;
				lab.BackColor = Color.Red;
			}
			lab.Text = dt.ToString();
			
			if(cont.Controls.Count > 0)
				lab.Top = cont.Controls[cont.Controls.Count-1].Top + cont.Controls[cont.Controls.Count-1].Height + 5;
			else
				lab.Top = 5;
			
			return lab;
		}

Leider führt auch das scrollen zum laggen... Gibt es vielleicht besser Möglichkeiten die ganzen Nachrichten anzuzeigen? Ich hoffe ihr könnt mir ein paar Anregungen geben 😃

Lieben Gruß Frokuss

16.806 Beiträge seit 2008
vor 6 Jahren

Chatfenster sind i.d.R. mit einer RichTextBox oder einem FlowDocument umgesetzt; oder komplett selbst zeichnen.
Aber die Menge an Controls ist für einen Chat sehr unüblich und unvorteilhaft.

PS:
Sowas wie FindControl macht Deine Routine langsam; nicht die Menge an Controls.
Alternative hier wäre das Zeug in einem Speicher zu halten statt ständig zu suchen (suchen => langsamer als Index-Zugriffe).

PPS: DateTime für Zeitmessungen im Millisekunden ist nicht die geeignetste Variante, um es nett auszudrücken.
Dafür gibt es die StopWatch-Klasse, die i.d.R. einen höher aufgelösten Counter im Hintergrund verwendet und damit genauer ist.

Oder in diesem Fall ganz einfach: nutze Profiler!
Dann siehst Du genau was lange dauert. Hier ermittelst Du nur die Zeit einer ganzen Routine statt einer einzelnen Aktion.
Und ohne den tatsächlich kritische Aktion zu ermitteln, kannst Du de facto auch keine Verbesserung erzielen.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Cool, danke für die Zahlreichen tipps. Werde die mal versuchen umzusetzen. Danke dir 😃

Gruß Frokuss

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Also funktional hat das alles gut geklappt. Die Ladezeiten sind deutlich runter gegangen - und dies lag nicht an dem FindControl (welches kaum eine Verbesserung geliefert hat).
Aber kann man die RichTextBox noch etwas aufpolieren? Daher den Text möglicherweise in eine Box (mit Hintergrundfarbe) stecken? Hier der (neue) aktuelle Code:

		private void ReadData2Chat(int id){
			Control cont = FindControl(this, "ChatVerlauf" + id);
			
			foreach(long t in chatKomplett[id].time){
				int i = chatKomplett[id].time.IndexOf(t);
				LabelMessageUAndMe(cont, id, chatKomplett[id].from2[i], chatKomplett[id].txt[i]);
			}
		}

//Die Methode scheint minimal überflüssig XD - wird/wurde aber aus drei verschiedenen anderen Methoden aufgerufen...
		private void LabelMessageUAndMe(Control cont, int id, int from, string txt){
			RichTextBox rtb = (RichTextBox)cont;

			rtb.AppendText(Environment.NewLine + txt);
			//cont.Controls.Add(lab);
		}

Gruß Frokuss

EDIT: Die Frage zielt darauf ab, dass ich die Nachrichten in einzelne Blasen stecken kann, die dann etwas aufpoliere. Daher runde ecken, hintergrundfarbe, rechts/links ausgerichtet...

16.806 Beiträge seit 2008
vor 6 Jahren

Schau doch bitte zunächst mal in die Dokumentation von RichTextBox...

.. hättest Du dies gleich gemacht, dann hättest Du gesehen, dass die RTB gewisse FlowDocument Elemente unterstützt.
Keiner hier weiß, was Du unter aufhübschen verstehst. Also werf ein Blick in die Doku und schau, ob Dir das reicht.
Danke.

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Öhm... Wenn ich das jetzt aber nicht falsch verstanden haben, dann sind FlowDocument Objekte nur für WPF-Anwendungen... Zumindestens wird bei mir gemeckert, wenn ich System.Windows.Document einzubinden. Dies geschieht aber nicht, wenn ich eine WPF-Anwendung habe...

Gruß Frokuss

16.806 Beiträge seit 2008
vor 6 Jahren

Woop - da schein ich die Dokumentation doch nicht auswendig zu kennen; in Forms gabs das ja tatsächlich nicht.

Dann musst Du Dir was anderes suchen, wenn Dir die RTB nicht reicht.
Aber ich bin mir sicher, dass Du hier fündig wirst - denn Du bist sicherlich nicht der Erste mit diesem Funktionswunsch 😉

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Höhö... ich habe den Fehler gefunden... Es waren nie 150 Labelns die erzeugt wurden... Es waren etwa 2000 welche bis grade eben auf über 4000 angewachsen sind... Nach einer begrenzung auf 200 Nachrichten, waren trotzdem alle Label instant da.

Ich danke euch für die Hilfe.

nachfolgend poste ich mal etwas Text für Richboxtexten, bei dem ich auch Bilder einfüge... Hilft vielleicht dem ein oder anderen 😃

Gruß Frokuss

//Control cont;
RichTextBox rtb = (RichTextBox)cont;
			
			var orgData = Clipboard.GetDataObject();
			Clipboard.SetImage(CornerI1);
			rtb.Paste();
			Clipboard.SetDataObject(orgData);
			
			rtb.AppendText(Environment.NewLine + txt);
			rtb.AppendText(Environment.NewLine);
			
			orgData = Clipboard.GetDataObject();
			Clipboard.SetImage(CornerI4);
			rtb.Paste();
			Clipboard.SetDataObject(orgData);
			rtb.AppendText(Environment.NewLine);