StringGrid Ram wird voll - Hilfe



  • Hallo,

    ich lese Datein aus einer Datenbank[Textdokument] Daten aus und lasse sie in einem StringGrid anzeigen.

    Habe jetzt mit den Task-Manager, das Programm beobachtet, der Ram-Speicher wird stätig hoher.

    Woran kann das liegen?

    Ich lösche schön am Ende die StringList!

    Edit:

    Vlt, werde ich noch ein paar Worte zu meinen Überlegungen:

    Möchte diese Daten in einem StringGrid, oder was besser dafür geeignetes, speichern, wenn man auf eine Zelle klickt mit >>OnClick<<, sollen einige Zelleninhalte zb in einem MemoFeld angezeigt werden.

    Cirka so:

    http://www.abload.de/img/unbenannt3lebn.jpg



  • Das kann ohne entsprechende Codeausschnitte nicht bewertet werden.



  • Was zur Hölle ?
    Da musst du aber entweder eine gehörige Datenbank lesen, oder an deinem
    Code stimmt etwas gewaltig nicht.
    Also bei einem 1024MB Ram musst du schon eine 900 MB Datenbank in den Stack lesen, und da du das in dem StringGrid angibst, müsste das Jahre dauern, zeig doch mal etwas Code, dann sieht man sicherlich was da das Problem auslöst.



  • so Tach, da bin ich wieder:

    ja der Code von mir ist etwas unübersichtlich.

    Daher habe ich die Probe mal aufs Example gemacht, um malzu schauen woran dieses Problem liegen könnte:

    http://img-host.de/bild.php/32624,screenVOPRG.png

    int i=1;
    while (i<100000){
    
    StringGrid1->RowCount++;
    StringGrid1->Cells[0][i]=i;
    StringGrid1->Cells[1][i]="Hallo";
    i++;
    }
    

    Der Taskmanager meldet folgendes:

    vor der Schleife: Projekt.exe || 1777k
    nach ""   ""    :    ""       || 36 424 k
    

    Bei zunnehmenden Text wird die Anwendung als größer, was ist da zu machen?

    Ist das vorerst als normal zu betrachten?

    Bei größeren Datensätzen wird das Programm dan arg langsam und belastet das System sehr!



  • Warum verwendest du überhaupt ein StringGrid für die Anzeige? Wenn du schon eine Datenbank hast kannst du ja TDBGrid nehmen. Das äre deutlich resourcenschonender da hier normalerweise nur die Daten geladen werden, die auch gerade angezeigt sind.



  • Ne ich würde das gerne über den StringGrid laufen lassen, da die vorgabe das so hergibt.



  • Na dann musst du das halt so lösen, das du auch nur die benötigten Daten in den sichtbaren Bereich lädst und nicht alles.



  • Das ist nur ein Auszug von einer Datenbank,Textdokument, hätte ich vlt nochmal korrekt beschreiben sollen.

    sollte ungefähr so Aussehen und funktionieren:

    http://www.abload.de/img/unbenannt3lebn.jpg



  • int i=1; 
    while (i<100000){ 
    
    StringGrid1->RowCount++; 
    StringGrid1->Cells[0][i]=i; 
    StringGrid1->Cells[1][i]="Hallo"; 
    i++; 
    }
    

    Laut diesem Code füllst du das StringGrid komplett mit allen Daten.
    Das ist extreme Resourcenverschwendung, da du vielleicht z.B. 20 Datensätze maximal anzeigst. Die 100000 stellst du niemals gleichzeitig dar.



  • asse schrieb:

    int i=1; 
    while (i<100000){ 
    
    StringGrid1->RowCount++; 
    StringGrid1->Cells[0][i]=i; 
    StringGrid1->Cells[1][i]="Hallo"; 
    i++; 
    }
    

    Laut diesem Code füllst du das StringGrid komplett mit allen Daten.
    Das ist extreme Resourcenverschwendung, da du vielleicht z.B. 20 Datensätze maximal anzeigst. Die 100000 stellst du niemals gleichzeitig dar.

    Hmm... hast recht, das ist auch bei bei der Resourcenbeobachtung ja nicht unübersehbar.
    Gibts da trotzdem keine Möglichkeit, viel darzustellen mit wenig oder konsequenter Resourcenabdeckung?



  • Hat doch Braunstein schon geschrieben.
    Am einfachsten ein TDBGrid verwenden.
    Wenn du aus welchen Gründen auch immer ein TStringGrid verwenden willst, dann ist das nunmal so dass du alles selbst reinkopieren musst.
    Und wenn du dann viele Daten hast, dann verbraucht das auch entsprechend Ressourcen.



  • bin zufällig auf der Suche nach einer Lösung auf folgendes getroffen und habe folgende Frage nun, wie wird dieses Problem hier gelöst?

    Screen:
    http://www.abload.de/img/unbenannt4reb.jpg

    ............................................................

    Ist das kein StringGrid?



  • Hallo

    Das kann alles möglich sein. Vor allem wenn diese Anwendung gar nicht mit dem Builder programmiert wurde.
    Ich vermute, daß das ein TListView ist. Damit kann man auch eher ein dynamisches Nachladen von Daten implementieren, um wenigstens nur die wirklich gebrauchten Daten laden zu müßen.

    bis bald
    akari



  • besteht bei TListView auch die Möglichkeit, die einzelnen Spalten anzusprechen?



  • Hallo

    Ja, über die Eigenschaft TListView::Items. Steht alles in der Builder-Hilfe.

    bis bald
    akari



  • Hab folgenden Code

    TListItem *Item;
    TListColumn *Column;
    
      Column = ListView1->Columns->Add();
      Column->Caption = "ID";
      Column->Width = 100;
      Column = ListView1->Columns->Add();
      Column->Caption = "Nname";
      Column->Width = 100;
      Column = ListView1->Columns->Add();
      Column->Caption = "geb";
    
    for (int i=0;i<80;i++)
    {
    	Item = ListView1->Items->Add();
    	Item->Caption = "Klasse G9"+IntToStr(i);
    
       Item->SubItems->Add(ID);
    	Item->SubItems->Add(Name);
    	Item->SubItems->Add(Nname);
    	Item->SubItems->Add(geb);
    }
    

    funktioniert soweit auch ganz gut,

    nur wie kann ich nun beim dblklick auf die Zeile, zb Zeilen NR und Spalten Nr einzeln ermitteln,zugreifen, sodass zb bei klick auf Nname der Nname im MemoFeld dargestellt wird.



  • keiner eine Idee?

    *
    
          als erstes sollte man sich eine Klasse definieren, die die Speicher-Objekte beschreibt (in einer Header-Datei) 
    
        class TListItemData
        {
    
            public:
    
            // Konstruktor der Klasse
            TListItemData(){};
    
            // Objektvariablen
            int iId;
            AnsiString sName;
    
        };
    
        *
    
          Um ein Objekt einem Listview-Item zuzuordnen muss man folgendermaßen vorgehen: 
    
        // Zeiger für das Listitem definieren
        TListItem *ListItem;
    
        // neues Listitem hinzufügen
        ListItem = ListView->Items->Add();
        ListItem->Caption = "Eintrag";
    
        // neues Datenobjekt erzeugen
        TListItemData *ItemData = new TListItemData();
        ItemData->iId = 1;
        ItemData->sName = "Horst";
    
        // Datenobjekt dem Listitem zuordnen (Zeiger übergeben)
        ListItem->Data = ItemData;
    
        *
    
          Der Zugriff auf ein solches Objekt kann wie folgt realisiert werden: 
    
        void __fastcall TForm1::ListViewClick(TObject *Sender)
        {
    
            if (ListView->Selected)
            {
    
                TListItemData *TempItem;
    
                // Datenzeiger vom akt. Listviewelement holen
                TempItem = (TListItemData*)ListView->Items->Item[i]->Data;
    
                // Wenn ein gültiger Zeiger vorhanden (!= NULL)
                if (TempItem)
                {
    
                    Label1->Text = IntToStr(ItemData->iId);
                    Label2->Text = ItemData->sName;
    
                }
                else // sonst Fehlermeldung
                {
    
                    ShowMessage("Objekt nicht verfügbar!");
    
                }
    
            }
    
        }
    
        *
    
          naturlich darf man das Löschen der so zugewiesenen Speicherobjekte nicht vergessen, dazu dient folgende Funktion: 
    
        void __fastcall TForm1::DeleteAllItemData()
        {
    
            TListItemData *TempItem;
    
            // Alle Items->Data des Listviews löschen
            for (int i=0; i<ListView->Items->Count; i++)
            {
    
                // Zeiger auf das akt. ListItem->Data->Objekt holen
                TempItem = (TListItemData*)ListView->Items->Item[i]->Data;
                if (TempItem)
                {
    
                    // alle Zeiger und Objekte löschen
                    ListView->Items->Item[i]->Data=NULL;
                    delete TempItem;
                    TempItem = NULL;
    
                }
    
            }
    
        }
    

    Hab das im Netz gefunden, aber fnktionieren tut es leider nicht!



  • Die einzelnen Einträge in der ListView sind vom Typ TListItem. Dieses hat die Eigenschaft SubItems, mit der Du auf die weiteren Spaltenwerte des Objektes zugreifen kannst.



  • sry doppelpost



  • ich habe das gleiche Problem beobachtet.
    Bei meiner Applikation lade ich große Dateien in StringGrid und von dort
    mache ich meine Datenauswertungen.
    Anschließend werden alle Zelleninhalte auf "" gesetzt und die Anzahl der
    Zeilen und Spalten auf 1 gesetzt.
    Und nach mehrmaligem Laden der Dateien wird nicht der ganze zuvor belegte
    Speicherbereich freigegeben.

    Ich denke, dass die TStringGrid irgendwo intern nicht ganz sauber programmiert
    wurde, und dass dadurch Speicherbereiche einfach belegt bleiben.


Log in to reply