In het programma dat ik aan het ontwikkelen ben, maak ik veel gebruik van strings en de bijbehorende functies Pos en Copy. Deze bewerkingen duren echter 8 sec. op een 266mHz en dat vind ik te lang. Is er een manier om Delphi in te stellen om beter te werken met strings? Kunnen threads nuttig zijn? (Zo ja, hoe dan precies?) Of is er ergens een unit die dit werk efficienter kan doen?
Er is niks dat sneller wordt van multithreading (iig in dit geval
), tenzij er meer cpu's beschikbaar zijn.
Waarschijnlijk moet je het aantal copies beperken en/of de bewerkingen op een lager type zien te krijgen (bijvoorbeeld een character-array, maar mijn delphi kennis laat me niet toe daarop een antwoord te bedenken
)
Waarschijnlijk moet je het aantal copies beperken en/of de bewerkingen op een lager type zien te krijgen (bijvoorbeeld een character-array, maar mijn delphi kennis laat me niet toe daarop een antwoord te bedenken
het lijkt me niet dat een pos en copy bewerking 8 sec. duurt. ik gebruik de pos functie zelf om strings waar een punt in staat te vervangen door een comma en het vervolgens om te zetten naar float. Dit gebeurd om een pentium 1 233 mhz en duurt nog geen seconde.
Dell XPS 17 Intel i7 2630 Nvidia GT555 3Gb Hd1: OCZ Vertex 2 SSD 60 GB Hd2: 500Gb
Verwijderd
Het is idd helaas waar dat strings in delphi sneller kunnen dan zoals ze nu geimplementeerd zijn. 
De assembly routines die dit zouden moeten verzorgen zijn niet geoptimaliseerd voor elke omstandigheid.
Hier wordt wat meer uitgelegd over hoe je dit kan optimaliseren.
http://www.borland.com/delphi/news/delphi_developer/optimizing.html
Hier kun je de snellere libs downen:
http://www.stuckindoors.com/delphi/
succes
De assembly routines die dit zouden moeten verzorgen zijn niet geoptimaliseerd voor elke omstandigheid.
Hier wordt wat meer uitgelegd over hoe je dit kan optimaliseren.
http://www.borland.com/delphi/news/delphi_developer/optimizing.html
Hier kun je de snellere libs downen:
http://www.stuckindoors.com/delphi/
succes
Het zijn meerdere (namelijk 100x) Pos- en Copy-bewerkingen.Op donderdag 18 april 2002 19:52 schreef marenk_vos het volgende:
het lijkt me niet dat een pos en copy bewerking 8 sec. duurt. ik gebruik de pos functie zelf om strings waar een punt in staat te vervangen door een comma en het vervolgens om te zetten naar float. Dit gebeurd om een pentium 1 233 mhz en duurt nog geen seconde.
Verwijderd
Je hebt er wel al 'n basis optimimalisatie over heen gehaald zoals niet meerderekeren met pos het zelfde tekentje in de zelfde string opzoeken ensow?Op donderdag 18 april 2002 20:44 schreef SiHiDa het volgende:
Het zijn meerdere (namelijk 100x) Pos- en Copy-bewerkingen.
Je bedoelt waarschijnlijk dit, he: FastStrings. Dit ziet er goed uit.Op donderdag 18 april 2002 20:07 schreef Materie het volgende:
Het is idd helaas waar dat strings in delphi sneller kunnen dan zoals ze nu geimplementeerd zijn.
De assembly routines die dit zouden moeten verzorgen zijn niet geoptimaliseerd voor elke omstandigheid.
Hier wordt wat meer uitgelegd over hoe je dit kan optimaliseren.
http://www.borland.com/delphi/news/delphi_developer/optimizing.html
Hier kun je de snellere libs downen:
http://www.stuckindoors.com/delphi/
succes
100x? Of 1000+ keer? Want 8 seconden lijkt me wel HEEL erg lang.Op donderdag 18 april 2002 20:44 schreef SiHiDa het volgende:
[..]
Het zijn meerdere (namelijk 100x) Pos- en Copy-bewerkingen.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Ik weet niet wat je precies wilt doen met pos en copy, maar misschien is de stringreplace() functie een mogelijkheid. Hangt er natuurlijk wel vanaf wat je wilt doen. Misschien kun je daar wat duidelijkheid over geven?
- This line is intentionally left blank -
Okee, waar ik het stukje voor nodig heb (op veler verzoek):
Ik ben bezig met het ontwikkelen van een GoT-Browser. Daarvoor wil ik graag uit een topiclist de titles, ID's, aantal Replies, enz. halen en deze in een soort van Listview plakken (voor de geinteresseerden ElTree uit het ElPack). Daarvoor gebruik ik de volgende code: (ik weet het, het is heel omslachtig, maar ik heb te weinig verstand van en Delphi en van de manier waarop HTML/GoT werkt.)
Ik weet het: het is niet erg overzichtelijk en er kan ipv 'if Kleur=4' ook een case-statement in, maar daar gaat het toch niet om? Misschien ook wel en is dat de remmende factor. Ik hoop dat ik nu duidelijk ben. (Als er een betere manier is om topics uit een topiclist te halen, vind ik dat natuurlijk ook best
)
Ik ben bezig met het ontwikkelen van een GoT-Browser. Daarvoor wil ik graag uit een topiclist de titles, ID's, aantal Replies, enz. halen en deze in een soort van Listview plakken (voor de geinteresseerden ElTree uit het ElPack). Daarvoor gebruik ik de volgende code: (ik weet het, het is heel omslachtig, maar ik heb te weinig verstand van en Delphi en van de manier waarop HTML/GoT werkt.)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
| var
Teller,Teller2,PreItem,Positie,HulpPositie,Kleur:integer;
Inhoud,HulpString,TopicID,Titel,DateTime,Replies,Starter:string;
Ms:TMemoryStream;
Str:TStringList;
ListItem:TElTreeItem;
TopicList:array of string;
begin
PreItem:=ComboBox1.ItemIndex;
if (Ini.ReadBool('Connectie','ConPag',False)) and (LoginState=True) and (CookieGeldig=False) then
begin
CookieNMGeldig;
if PreItem in [23..27] then
Exit;
end;
Button1.Enabled:=False;
HttpCli1.Cookie:=Cookie;
HttpCli1.URL:=HaalLinkVanForum(ComboBox1);
Ms:=TMemoryStream.Create;
HttpCli1.RcvdStream:=Ms;
HttpCli1.Get;
Ms.Seek(0, 0);
Str:=TStringList.Create;
Str.LoadFromStream(Ms);
for Teller:=0 to Str.Count-1 do
for Teller2:=0 to Length(Str[Teller]) do
begin
HulpString:=Str[Teller];
Inhoud:=Inhoud+HulpString[Teller2];
end;
HttpCli1.RcvdStream.Destroy;
HttpCli1.RcvdStream := nil;
ElTree1.Items.Clear;
Positie:=Pos('topic(',Inhoud);
Inhoud:=Copy(Inhoud,Positie,Length(Inhoud)-Positie);
HulpPositie:=Pos('/SCRIPT',Inhoud);
Inhoud:=Copy(Inhoud,1,HulpPositie);
Positie:=1;
HulpPositie:=Pos(#39+');',Inhoud);
repeat
SetLength(TopicList,Length(TopicList)+1);
for Teller:=Positie+7 to HulpPositie-1 do
TopicList[High(TopicList)]:=TopicList[High(TopicList)]+Inhoud[Teller];
Inhoud:=Copy(Inhoud,HulpPositie+4,Length(Inhoud)-HulpPositie);
Positie:=Pos('topic(',Inhoud);
HulpPositie:=Pos(#39+');',Inhoud);
until Positie=0;
for Teller:=Low(TopicList) to High(TopicList) do
begin
HulpPositie:=Pos('/',TopicList[Teller]);
TopicID:=Copy(TopicList[Teller],1,HulpPositie-1);
Positie:=Pos(',',TopicList[Teller]);
Kleur:=StrToInt(TopicList[Teller][Positie+1]);
Positie:=Positie+6;
repeat
Titel:=Titel+TopicList[Teller][Positie];
Positie:=Positie+1;
until (TopicList[Teller][Positie]='<') or (TopicList[Teller][Positie]=#39);
if TopicList[Teller][Positie]='<' then
begin
TopicList[Teller]:=Copy(TopicList[Teller],Positie,Length(TopicList[Teller])-Positie);
Positie:=Pos(#39,TopicList[Teller]);
end;
Positie:=Positie+3;
repeat
Starter:=Starter+TopicList[Teller][Positie];
Positie:=Positie+1;
until TopicList[Teller][Positie]=#39;
Positie:=Positie+2;
repeat
Replies:=Replies+TopicList[Teller][Positie];
Positie:=Positie+1;
until TopicList[Teller][Positie]=',';
for Teller2:=Positie+2 to Length(TopicList[Teller]) do
DateTime:=DateTime+TopicList[Teller][Teller2];
ListItem:=ElTree1.Items.AddItem(ElTree1.Items[ElTree1.Items.Count]);
ListItem.Text:=Titel;
ListItem.ColumnText.Add(TopicID);
ListItem.ColumnText.Add(Replies);
ListItem.ColumnText.Add(Starter);
if (DateTime<> '') and (DateTime<>' ') then
ListItem.ColumnText.Add(DateTime);
if Kleur=8 then
ListItem.ImageIndex:=4;
if Kleur=5 then
ListItem.ImageIndex:=3;
if Kleur=4 then
ListItem.ImageIndex:=2;
if Kleur=3 then
ListItem.ImageIndex:=1;
if Kleur=2 then
ListItem.ImageIndex:=0;
TopicID:='';
Replies:='';
Starter:='';
DateTime:='';
Titel:='';
end;
Button1.Enabled:=True; |
Ik weet het: het is niet erg overzichtelijk en er kan ipv 'if Kleur=4' ook een case-statement in, maar daar gaat het toch niet om? Misschien ook wel en is dat de remmende factor. Ik hoop dat ik nu duidelijk ben. (Als er een betere manier is om topics uit een topiclist te halen, vind ik dat natuurlijk ook best
Verwijderd
Ik heb heel vluchtig je code bekeken en daar zijn zeer zeker vele zaken te verbeteren:
1) Probeer eerst alles in procedures/functies om te zetten i.p.v. één lange brei (een proc/functie met meer dan 10 regels is over het algemeen al onoverzichtelijk).
2) Houdt het aantal variabelen zo beperkt mogelijk; probeer maar eens de variabelen welke je slechts één keer gebruikt weg te laten en te vervangen door de echte functie (met name bij bijv. de functie Pos).
3) Vermijdt code als:
Dit kun je ook schrijven als:
4) Je maakt gebruik van een stringlist en vervolgens lees je ieder item in. Dit kun je veel eenvoudiger doen met de volgende code:
5) Je gebruikt de functies Delete en Insert niet. Kijk daar eens naar.
6) Je gebruikt een dynamische array en verhoogt bij iedere iteratie de lengte van deze array. Dit neemt HEEL veel tijd in! Gebruik dan liever een TList o.i.d. met bijv. PChars.
7) Je gebruikt de Destroy i.p.v. Free. Hoewel dit niet fout is is het niet slim. Free gaat altijd goed, Destroy niet! Bij een TForm gebruik je Release btw. Vanaf Delphi 5 kun je ook FreeAndNil gebruiken om vrij te geven en meteen naar nil te assignen.
Je gebruikt LongStrings; Delphi kent ook ShortStrings. Hoewel deze maximaal 255 karakters lang is zijn ze wel sneller. Bovendien bevat karakter 0 van een shortstring de lengte van de shortstring zodat functies als Length niet nodig zijn.
Dit zijn zo 8 punten die ik er snel uit kon halen. Er is vast nog wel meer prestatie winst te behalen maar optimaliseer eerst zo je routines maar eens en dan ga je nog weer een stapje verder.
1) Probeer eerst alles in procedures/functies om te zetten i.p.v. één lange brei (een proc/functie met meer dan 10 regels is over het algemeen al onoverzichtelijk).
2) Houdt het aantal variabelen zo beperkt mogelijk; probeer maar eens de variabelen welke je slechts één keer gebruikt weg te laten en te vervangen door de echte functie (met name bij bijv. de functie Pos).
3) Vermijdt code als:
code:
1
2
| while Pos(#39, sTxt)>0 do sTxt[Pos(#39, sTxt)]:=' '; |
Dit kun je ook schrijven als:
code:
1
| sTxt:=StringReplace(sTxt, #39, ' ', [rfReplaceAll]); |
4) Je maakt gebruik van een stringlist en vervolgens lees je ieder item in. Dit kun je veel eenvoudiger doen met de volgende code:
code:
1
| sTxt:=StringReplace(StrLst.Text, #13#10, '', [rfReplaceAll]); |
5) Je gebruikt de functies Delete en Insert niet. Kijk daar eens naar.
6) Je gebruikt een dynamische array en verhoogt bij iedere iteratie de lengte van deze array. Dit neemt HEEL veel tijd in! Gebruik dan liever een TList o.i.d. met bijv. PChars.
7) Je gebruikt de Destroy i.p.v. Free. Hoewel dit niet fout is is het niet slim. Free gaat altijd goed, Destroy niet! Bij een TForm gebruik je Release btw. Vanaf Delphi 5 kun je ook FreeAndNil gebruiken om vrij te geven en meteen naar nil te assignen.
Dit zijn zo 8 punten die ik er snel uit kon halen. Er is vast nog wel meer prestatie winst te behalen maar optimaliseer eerst zo je routines maar eens en dan ga je nog weer een stapje verder.
Heb je zeker gelijk in, maar voor de snelheid maakt het niet veel uit, lijkt me.Op vrijdag 19 april 2002 16:04 schreef hvdberg het volgende:
Ik heb heel vluchtig je code bekeken en daar zijn zeer zeker vele zaken te verbeteren:
1) Probeer eerst alles in procedures/functies om te zetten i.p.v. één lange brei (een proc/functie met meer dan 10 regels is over het algemeen al onoverzichtelijk).
Maar is het niet sneller om de waarde van een functie die dan 3 keer achter elkaar moet worden uitgevoerd (en hetzelfde resultaat geeft) aan een variable toe te kennen? 1 variabele minder of meer betekent toch niet veel?2) Houdt het aantal variabelen zo beperkt mogelijk; probeer maar eens de variabelen welke je slechts één keer gebruikt weg te laten en te vervangen door de echte functie (met name bij bijv. de functie Pos).
Maar nog steeds geen tijdswinst...3) Vermijdt code als:
code:
1 2 while Pos(#39, sTxt)>0 do sTxt[Pos(#39, sTxt)]:=' ';
Dit kun je ook schrijven als:
code:
1 sTxt:=StringReplace(sTxt, #39, ' ', [rfReplaceAll]);
Misschien eenvoudiger, maar in dit onderdeel van de code zit de belemmering niet. Hier gaat hij binnen 10 ms doorheen.4) Je maakt gebruik van een stringlist en vervolgens lees je ieder item in. Dit kun je veel eenvoudiger doen met de volgende code:
code:
1 sTxt:=StringReplace(StrLst.Text, #13#10, '', [rfReplaceAll]);
Met betrekking tot wat?5) Je gebruikt de functies Delete en Insert niet. Kijk daar eens naar.
Hier gaat hij ook binnen 10ms doorheen...6) Je gebruikt een dynamische array en verhoogt bij iedere iteratie de lengte van deze array. Dit neemt HEEL veel tijd in! Gebruik dan liever een TList o.i.d. met bijv. PChars.
Weer: geen echte snelheidswinst...7) Je gebruikt de Destroy i.p.v. Free. Hoewel dit niet fout is is het niet slim. Free gaat altijd goed, Destroy niet! Bij een TForm gebruik je Release btw. Vanaf Delphi 5 kun je ook FreeAndNil gebruiken om vrij te geven en meteen naar nil te assignen.
Heb het uitgeprobeerd, maar maakt niet veel uit.Je gebruikt LongStrings; Delphi kent ook ShortStrings. Hoewel deze maximaal 255 karakters lang is zijn ze wel sneller. Bovendien bevat karakter 0 van een shortstring de lengte van de shortstring zodat functies als Length niet nodig zijn.
Probeer es te bepalen waar ie zo lang over doet dan, als hij met geen van deze genoemde optimalisaties versnelt moet het ergens anders in zitten, of niet 
En 100x 10ms is natuurlijk wel 1 seconde
En 100x 10ms is natuurlijk wel 1 seconde
Maar het is dan wel makkelijker te bepalen in welke procedure/functie zoveel tijd wordt besteed en wat er dus geoptimaliseerd moet worden.Op vrijdag 19 april 2002 19:11 schreef SiHiDa het volgende:
[..]
Heb je zeker gelijk in, maar voor de snelheid maakt het niet veel uit, lijkt me.
[..]
Weet je dat zeker? Heb je dat getest? Elke milliseconde is er 1 he.Maar is het niet sneller om de waarde van een functie die dan 3 keer achter elkaar moet worden uitgevoerd (en hetzelfde resultaat geeft) aan een variable toe te kennen? 1 variabele minder of meer betekent toch niet veel?
[..]
Maar nog steeds geen tijdswinst...
[..]
Zoals al gezegd: 100 keer 10 ms = 1 sec. Eenvoudigere code is ook eenvoudiger te optimaliseren.Misschien eenvoudiger, maar in dit onderdeel van de code zit de belemmering niet. Hier gaat hij binnen 10 ms doorheen.
[..]
Met die functies kan je stukken string uit een string halen. Dit is wat jij hier flink aan het doen bent, dus waarom zou ej zeniet gebruiken?Met betrekking tot wat?
[..]
Geen echte?? Dus wel snelheids winst! Elke winst die je kan makkelijk kan pakken, pakken!Hier gaat hij ook binnen 10ms doorheen...
[..]
Weer: geen echte snelheidswinst...
[..]
Maar het maakt dus wel wat uit....Heb het uitgeprobeerd, maar maakt niet veel uit.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Verwijderd
Als je de code vanaf
weg haalt, hoe snel doet hij er dan over?
Heeft die ElTree1 geen BeginUpdate en EndUpdate, en gebruik je die ook?
Het probleem zit dus misschien in het updaten van een visueel component.
code:
1
| ListItem:=ElTree1.Items.AddItem(ElTree1.Items[ElTree1.Items.Count]); |
weg haalt, hoe snel doet hij er dan over?
Heeft die ElTree1 geen BeginUpdate en EndUpdate, en gebruik je die ook?
Het probleem zit dus misschien in het updaten van een visueel component.
Verwijderd
Ik heb een vb gemaakt hoe je met PChar's werkt; hiermee voorkom je kostbare code zoals
Dit is dus de laatste lus in jouw code; de code heb ik niet getest BTW
code:
1
| Titel:=Titel+TopicList[Teller][Positie]; |
Dit is dus de laatste lus in jouw code; de code heb ik niet getest BTW
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| var
P, Q: PChar;
begin
//HulpPositie := Pos('/', TopicList[Teller]);
//TopicID := Copy(TopicList[Teller], 1, HulpPositie - 1);
Q := PChar(TopicList[Teller]);
P := StrScan(Q, '/');
Assert(P <> nil, 'Geen / gevonden');
SetLength(TopicID, P - Q);
Move(Q^, PChar(TopicID)^, P - Q);
//Positie := Pos(',', TopicList[Teller]);
P := StrScan(Q, ',');
Assert(P <> nil, 'Geen , gevonden');
//Kleur := StrToInt(TopicList[Teller][Positie + 1]);
Kleur := StrToInt((P + 1)^);
//Positie := Positie + 6;
Inc(P, 6);
//repeat
// Titel := Titel + TopicList[Teller][Positie];
// Positie := Positie + 1;
//until (TopicList[Teller][Positie] = '<') or
// (TopicList[Teller][Positie] = #39);
{ Met Q markeren we de startpositie }
Q := P;
Inc(P);
while not (P^ in ['<', #39]) do
Inc(P);
SetLength(Titel, P - Q);
Move(Q^, PChar(Titel)^, P - Q);
//if TopicList[Teller][Positie] = '<' then
//begin
// TopicList[Teller] := Copy(TopicList[Teller], Positie,
// Length(TopicList[Teller]) - Positie);
// Positie := Pos(#39, TopicList[Teller]);
//end;
{ Als P al op een #39 staat, zal P niet veranderen }
P := StrScan(P, #39);
Assert(P <> nil, 'Geen #39 gevonden');
//Positie := Positie + 3;
Inc(P, 3);
//repeat
// Starter := Starter + TopicList[Teller][Positie];
// Positie := Positie + 1;
//until TopicList[Teller][Positie] = #39;
Q := P;
Inc(P);
StrScan(P, #39);
Assert(P <> nil, 'Geen #39 gevonden');
SetLength(Starter, P - Q);
Move(Q^, PChar(Starter)^, P - Q);
//Positie := Positie + 2;
Inc(P, 2);
//repeat
// Replies := Replies + TopicList[Teller][Positie];
// Positie := Positie + 1;
//until TopicList[Teller][Positie] = ',';
Q := P;
Inc(P);
StrScan(P, ',');
Assert(P <> nil, 'Geen , gevonden');
SetLength(Replies, P - Q);
Move(Q^, PChar(Replies)^, P - Q);
//for Teller2 := Positie + 2 to Length(TopicList[Teller]) do
// DateTime := DateTime + TopicList[Teller][Teller2];
Inc(P, 2);
Q := P;
StrScan(P, #0);
Assert(P <> nil, 'Geen #0 gevonden');
SetLength(DateTime, P - Q);
Move(P^, PChar(DateTime)^, P - Q);
end; |
edit:
P-Q-1 => P-Q
P-Q-1 => P-Q
Precies.Op zaterdag 20 april 2002 14:09 schreef DiFool het volgende:
Als je de code vanaf
code:
1 ListItem:=ElTree1.Items.AddItem(ElTree1.Items[ElTree1.Items.Count]);
weg haalt, hoe snel doet hij er dan over?
Heeft die ElTree1 geen BeginUpdate en EndUpdate, en gebruik je die ook?
Het probleem zit dus misschien in het updaten van een visueel component.
Verwijderd
Veel visuele componenten hebben een BeginUpdate en een EndUpdate method; hiermee geef je aan dat je het component aan het updaten bent, en dat het component zichzelf in die tijd niet - bij elke aanpassing - moet hertekenen.
Thanx, dat wist ik niet.Op zaterdag 20 april 2002 14:54 schreef DiFool het volgende:
Veel visuele componenten hebben een BeginUpdate en een EndUpdate method; hiermee geef je aan dat je het component aan het updaten bent, en dat het component zichzelf in die tijd niet - bij elke aanpassing - moet hertekenen.
Verwijderd
Bij mij ging 't vullen van een TreeView na het gebruik van BeginUpdate/EndUpdate van 80 seconden naar 0,3 seconde.Op zaterdag 20 april 2002 15:26 schreef SiHiDa het volgende:
Thanx, dat wist ik niet.Ik zal nu alle dingen die in dit artikel genoemd zijn, uitproberen en dan meld ik hier de resultaten. Wordt vervolgd.
Wel de moeite waard om als eerste naar te kijken, lijkt me.
Precies, de procedure is inmiddels al ruim 75% sneller. Ik ben tevreden.Op zaterdag 20 april 2002 18:36 schreef Afterlife het volgende:
[..]
Bij mij ging 't vullen van een TreeView na het gebruik van BeginUpdate/EndUpdate van 80 seconden naar 0,3 seconde.
Wel de moeite waard om als eerste naar te kijken, lijkt me.
Dat gaat ook op voor het leegmaken van een TreeView. BeginUpdate - Clear - EndUpdate in de OnClose van je form kan er soms voor voor zorgen dat je applicatie seconden sneller afsluit.Bij mij ging 't vullen van een TreeView na het gebruik van BeginUpdate/EndUpdate van 80 seconden naar 0,3 seconde.
Wel de moeite waard om als eerste naar te kijken, lijkt me.
Een goede grap mag vrienden kosten.
Pagina: 1