2017-10-28 3 views
4

Ich habe 100000 Zeilen in einem TMemo. Ich möchte etwas tun wie:TMemo ist schmerzhaft langsam beim Arbeiten mit einer großen Anzahl von Zeilen

aber die Geschwindigkeit beträgt 0,5 Zeilen pro Sekunde !!

Nach dem Hinzufügen von BeginUpdate/EndUpdate sehe ich keine Geschwindigkeitsverbesserung.

Memo.Lines.BeginUpdate; 
for i:= 0 to Memo.Lines.Count-1 do 
    Memo.Lines[i]:= SomeTrim(Memo.Lines[i]); 
Memo.Lines.EndUpdate; 

Meine Frage ist, warum BeginUpdate/EndUpdate wird nicht helfen?

+3

Schlechter Benutzer, der eine solche Notiz scrollen wird. – Victoria

+0

PS: Die aktuelle Lösung besteht darin, die Zeilen einer TStringList zuzuordnen, sie zu verarbeiten und sie wieder in das Memo einzufügen. Aber ich bin immer noch neugierig, warum BeginUpdate nicht funktioniert. – Ampere

+0

@Victoria - Der Benutzer wird diese Zeilen dort platzieren. Normalerweise erwarte ich unter 100 Zeilen. Ich wollte testen, was mit 100000 passiert. Und das passiert. – Ampere

Antwort

10

TStrings.BeginUpdate/EndUpdate werden nur die Ereignisse OnChanging und OnChanged verbieten. Es hat keinen Einfluss auf die interne Bearbeitung der Änderungen am Inhalt selbst.

TMemo.Lines wird von TMemoStrings implementiert, die den Textinhalt im Window-Steuerelement selbst speichert. Also BeginUpdate/EndUpdate ist hier ziemlich nutzlos.

Sie können bessere Ergebnisse erhalten, indem eine lokale TStringList Instanz verwendet wird, und mit Hilfe der Text Eigenschaft der Daten von TMemo zu TStringList und zurück zu kopieren. Die Eigenschaft ist die effizienteste Möglichkeit, auf den gesamten Inhalt einer TMemo gleichzeitig zuzugreifen.

lst := TStringList.Create; 
    try 
    lst.Text := Memo1.Lines.Text; 
    for I := 0 to lst.Count - 1 do begin 
     lst[I] := SomeTrim(lst[I]); 
    end; 
    Memo1.Lines.Text := lst.Text; 
    finally 
    lst.Free; 
    end; 

Hinweis: erwähnen Einige Kommentare Assign anstelle der Text Eigenschaft zu verwenden, wenn der Inhalt von und zu dem Memo zu kopieren: Assign ist in diesem Fall wesentlich langsamer aufgrund einer internen Optimierung der Text Eigenschaft für TMemoLines . Getter und Setter dieser Eigenschaft greifen direkt auf das Windows-Steuerelement mit einer einzigen WM_GETTEXT/WM_SETTEXT-Nachricht zu, während Assign eine EM_GETLINE-Nachricht pro Zeile zum Lesen und eine Sequenz von EM_LINEINDEX, EM_SETSEL, EM_LINELENGTH und EM_REPLACESEL pro Zeile zum Schreiben verwendet. Ein einfacher Timing-Test zeigt, dass der obige Code ungefähr 600 ms benötigt, während das Ersetzen der Zuweisungen durch Assign Aufrufe mehr als 11 Sekunden benötigt!

+5

Verwenden Sie die 'Assign()' Methode anstelle der 'Text' Eigenschaft:' lst.Assign (Memo1.Lines); ... Memo1.Lines.Assign (lst); 'Da die Zeilen bereits getrennt sind, kopieren Sie sie einfach wie sie sind, verketten Sie sie nicht, nur um sie erneut zu analysieren, das ist eine Verschwendung von Speicher und Verarbeitung –

+0

@RemyLebeau Das Abrufen und Einstellen jeder Zeile ist eigentlich der ursprüngliche Code. –

+9

Ich bin mir dessen bewusst. Ich beziehe mich darauf, den Memo-Inhalt in die StringList und dann zurück zu kopieren. Ihre Antwort besagt, dass die 'Text' -Eigenschaft die" effizienteste "Methode ist, dies zu tun, aber das ist nicht einmal im Entferntesten richtig, besonders für 100000 Zeilen. Der 'Text'-Getter führt einen 2-Durchlauf-Scan durch, um Speicher zuzuordnen und zu kopieren, dann analysiert der' Text'-Setzer die Eingabe, um eine VIELE Zuordnungen durchzuführen. 'Assign() 'andererseits führt viel weniger Zuweisungen aus und verwendet einen 1-Durchlauf-Scan. Profilieren Sie es für sich selbst, 'Assign()' ist effizienter als 'Text' –

Verwandte Themen