![]() |
hat TStringgrig eine innere Größenbeschränkung?
Guten Tag zusammen,
bei der Ausgabe einer Datenbankabfrage erhalte ich folgenden Fehler: Benachrichtigung über Debugger-Exception --------------------------- Im Projekt SQL_CLIENT.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 0047FBE9 in Modul 'SQL_CLIENT.exe'. Lesen von Adresse 0003FFFC' aufgetreten. Dann sind ca 150.000 der 240.000 Datensätze verarbeitet. lenke ich die Ausgabe in ein TMemo um ist der Speicherverbrauch nicht ganz so hoch (ist ja eigentlich klar) und alles klappt. hier der zugehörige Source-Code:
Delphi-Quellcode:
Ich vermute, daß schlicht und ergreifend der Speicher am Ende ist, und das darum die obige Fehlermeldung Blödsinn ist. Oder liege ich da falsch?
procedure INSTRINGGRID(ins:string;sg:tstringgrid);
var i : integer; fldcnt : integer; begin fldcnt:=1; for i:=1 to length(ins) do if ins[i]=#9 then inc(fldcnt,1); if sg.ColCount<fldcnt then sg.colcount:=fldcnt; for i:=1 to fldcnt do sg.cells[i-1,sg.rowcount-1]:=feld(ins,i); sg.rowcount:=sg.rowcount+1; end; for i:=0 to tl.count-1 do begin try INSTRINGGRID(tl[i],form1.StringGrid1); except showmessage('Fehler bei Datenausgabe in Stringgrid aufgetreten Datensatz Nr'+inttostr(i)); break; end; form1.L_Grid_Count.caption:=inttostr(i)+' von '+inttostr(tl.count); end; |
AW: hat TStringgrig eine innere Größenbeschränkung?
Wie sinnvoll ist es 240.000 Datensätze in einem Grid anzuzeigen?
|
AW: hat TStringgrig eine innere Größenbeschränkung?
Ich würde mich Deiner Vermutung und der Frage MKinzlers anschliessen
|
AW: hat TStringgrig eine innere Größenbeschränkung?
Diese Zeile
Delphi-Quellcode:
ist natürlich besonders schmerzhaft.
sg.rowcount:=sg.rowcount+1;
Durch das Anhängen von einzelnen Zeilen werden intern jede Menge Speicherreservierung vorgenommen und zig Windows-Messages verschickt. Wenn man das Grid von Anfang an die richtige Grösse gibt, dann wird es viel effizienter. |
AW: hat TStringgrig eine innere Größenbeschränkung?
Zitat:
:stupid: |
AW: hat TStringgrig eine innere Größenbeschränkung?
erst einmal vielen Dank!
die 240.000 Datensätze sind dann sinnvoll, wenn mann versucht heraus zu bekommen, was eigentlich in der Tabelle steht. (das Extrem-Scrolling ist gut! muß ich mal versuchen) Zitat:
Die OH war da nicht so eindeutig, und die Praxis schein nicht dagegen zu sprechen. Gruß K-H |
AW: hat TStringgrig eine innere Größenbeschränkung?
Schau den benötigten Speicher an?
Integriert FastMM um die Speicherfragmentierung des alten Memory-Managers zu umgehen. |
AW: hat TStringgrig eine innere Größenbeschränkung?
fastMM war eine gute Empfehlung. Da ist prompt eine Schusseligkeit in einer alten Unit hochgekommen, aber der Fehler bleibt.
Ich hab es mal mit
Delphi-Quellcode:
versucht.
for i:=0 to maxint do
stringgrid1.cells[0,i]:=inttohex(i,8); Das läuft, wie zu erwarten, vor die Speicherwand. Es sieht so aus, als würde der Fehler durch eine bestimmte Kombination aus Daten/Satznummer verursacht. Mal weiter testen, vielleicht finde ich noch etwas. Edith: Jetzt ist der Cursor zum ersten Mal im Sourcecode zu sehen gewesen. Könnt Ihr mit dieser Routine etwas anfangen?
Delphi-Quellcode:
Gruß
unit Grids
function TSparsePointerArray.MakeAt(Index: Integer): PPointer; var dirP: PSecDir; p: Pointer; byteP: PChar; secIndex: Word; begin { Expand Section Directory if necessary. } secIndex := Index shr secShift; { Unsigned shift } if secIndex >= slotsInDir then dirP := expandDir(secDir, slotsInDir, secIndex + 1) else dirP := secDir; { Index into Section Directory using high order part of index. Get pointer to Section. If null, create new Section. Index into Section using low order part of index. } secDir := dirP; p := dirP^[secIndex];{------------------------------ hier stet der Cursor !!!!! if p = nil then begin p := makeSec(secIndex, FSectionSize); dirP^[secIndex] := p end; byteP := p; Inc(byteP, (Index and indexMask) * SizeOf(Pointer)); if Index > FHighBound then FHighBound := Index; Result := PPointer(byteP); cachedIndex := -1 end; K-H |
AW: hat TStringgrig eine innere Größenbeschränkung?
Zitat:
Das ist eine völlig andere Größenordnung als ~300000. Zitat:
Also ein Stringgrid mit 300000 Zeilen ist eigentlich "gar kein Problem":
Delphi-Quellcode:
Die Schleife braucht zwar ~4 Minuten bis sie fertig ist,
var
i : Integer; begin StringGrid1.RowCount := 300000; // VORHER setzen ! for i := 1 to StringGrid1.RowCount-1 do StringGrid1.Cells[1, i] := IntToStr(i); end; aber Anzeigen und Scrollen funktioniert. Interessanterweise dauert das Beenden des Programms ca 1,5 Minuten; im Hintergrund werden wohl einige Hunderttausende Windows-Botschaften verschickt und das braucht Zeit. |
AW: hat TStringgrig eine innere Größenbeschränkung?
Zitat:
Zitat:
Gruß K-H |
AW: hat TStringgrig eine innere Größenbeschränkung?
Also die Hinweise zusammengeworfen, (wenn schon die ganze Datenbank eingelesen und angezeigt werden muss) würde es am meisten Sinn machen, die Daten in einen schnellen "Container" einzulesen.
Also Daten erst in ein passendes dyn. Array einlesen und über eine simple Funktion die Werte für die jeweilige Zeile/Spalte bereitstellen (ist im Ausgangspost ja quasi schon vorhanden)
Delphi-Quellcode:
.
function GetDatabaseArrayValue(ACol, ARow): String;
Nach dem Einlesen ist RowCount bekannt und kann im StringGrid gesetzt werden. Das StringGrid wird jetzt nicht gefüllt sonder wie mkinzler vorgeschlagen hat, nur der sichtbare Bereich via DrawCell angezeigt (Beispiel mit einer fixed Row):
Delphi-Quellcode:
procedure TForm1.StringGrid1DrawCell(Sender: TObject;
ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var s : String; begin with (Sender as TStringGrid) do begin if gdFixed in State then SetTextStyle(Canvas, clBtnFace, clBtnText, []) else if gdSelected in State then SetTextStyle(Canvas, clHighlight, clHighlightText, []) else SetTextStyle(Canvas, clWindow, clWindowText, []); if ARow = 0 then s := Cells[Acol,Arow] else s := GetDatabaseArrayValue(ACol, ARow); Canvas.TextRect(Rect,Rect.Left +2,Rect.Top+2, s); end; end; |
AW: hat TStringgrig eine innere Größenbeschränkung?
@Satty67
Das wird das beste sein. Mal sehen was ich damit anfangen kann. Ich würde es so benennen: "Ein Browserfenster über die Daten gleiten lassen." Da als alternative Ausgabe Text/TMemo vorhanden ist kann man da gleich Nägel mit Köpfen machen. CopyundPaste bliebe dann zwar auf der Strecke habe ich bisher aber nicht benötigt. Ich hab mal an der Ausgangsfragestellung weiter gebastelt und würde jetzt "ja" sagen. (zumindestens bei Stringgrids mit weniger als 512 Cols) Mein Fehler tritt immer dann auf, wenn das Stringgrid x7FFF80 oder mehr Cells enthalten soll. egal ob der Eintrag in das Grid über Cells[x,y] oder Rows[y] erfolgt. bevor es jemand anmerkt, ja RowCount und CellCount waren initialisiert. Vielen Dank an alle, die sich Ihren Kopf darüber zerbrochen haben. Gruß K-H |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz