vložil Radek Červinka
4. května 2010 00:06
O debug vizualizérech v Delphi 2010 jsem již psal. Jen pro zopakování - jsou dva typy: jeden trasformuje datový typ (např. TDateTime) na srozumitelnější text, druhý zobrazuje okno (např. z instalace Delphi je vizualizer pro TStringList).
Implementace druhého je náročnější, jelikož se musí využít ToolsAPI debuggeru a přistupovat do jiného procesu během ladění a navíc příkazy pro zjišťování informací pro zobrazení se za běhu kompilují (stejně jako to dělá IDE ve WatchListu). Osobně vím jen o jedné plnohodnotné implementaci takového vizualizeru pro TBitmap, a o jedné, která je strašně pomalá, až se stydím, že jsem ji vůbec napsal - pro TDataSet.

TBitmap vizualizer
TBitmap vizualizér používá pro slušnou rychlost několik opravdu špinavých triků.

TDataset vizualizer
Problém mého vizualizéru je pomalost - pro trochu větší počet fieldů trvá zobrazení i 10s. A bohužel opravdu nevím jak to zrychlit. Principem takového vizualizéru je, jak již jsem uvedl, využití ToolsAPI Delphi - v tomto případě ToolsAPI debuggeru. Klíčovou metodou je volání ToolsAPI Evaluate, které provede vyhodnocení zadaného výrazu (výraz se interně kompiluje a pak nějak díky meziprocesorové komunikací se vyhodnotí a výsledek vrátí).
Bylo mi poraděno na stackoverflow abych se snažil co nejvíce příkazů sloučit do volání funkce Evaluate, ale zdá se mi, že to moc nepomáhá a navíc to přináší více problémů. Takže jen pro zajímavost a třeba to někomu pomůže - FExpression je výraz, nad kterým byl evaluátor vyvolán - např. Dataset1. Popř. kdyby měl někdo nějaký nápad - tak sem s ním. Ale předem říkám, že získat adresu objektu a tu přetypovat a volat přímo metody TDatasetu nejde, resp. získat adresu a přetypovat samozřejmě lze, ale nelze k nim dále přistupovat.
1procedure TDataSetViewerFrame.mFillData;
2var
3 iCount: Integer;
4 I: Integer;
5 sw: TStopwatch;
6 s: string;
7begin
8 sw := TStopwatch.StartNew;
9 iCount := StrToIntDef(Evaluate(FExpression+'.Fields.Count'), 0);
10 for I := 0 to iCount - 1 do
11 begin
12 s:= s + Format('%s.Fields[%d].FieldName+'',''+', [FExpression, I]);
13
14 FValues.Add(Evaluate(Format('%s.Fields[%d].Value', [FExpression, I])));
15 end;
16 if s<> '' then
17 Delete(s, length(s)-4, 5);
18 s := Evaluate(s);
19 s:= Copy(s, 2, Length(s) -2);
20 FFields.CommaText := s;
21 sw.Stop;
22 s := sw.Elapsed;
23
24end;
Pokud by chtěl někdo psát vlastní vizualizér, doporučuji vycházet z toho pro TBitmap, je tam vytvořena rozumná základní třída. Já to zjistil, až jsem to měl napsané.