Arbeitsspeicher läuft über die Zweite :)



  • Hi Leute,
    Seht euch meinen Code mal an- das einzige, was ich praktizieren möchte ist, dass ein Männchen über den Bildschirm läuft.
    Doch irgendwie ist der RAM von mir schon nach wenigen Sekunden komplett voll, weil ich im Thread bei jedem schleifendurchlauf den Buffer (damits nicht flimmert ihr wisst schon) mit nem neuen Bild befülle.
    Leider weiß ich nicht, wie ich den lösche und überhaupt hab ich das Gefühl, dass das irgendwie nicht der richtige Weg ist, denn mit "delete buffer" gehts nicht 😞
    Ich würd mich freuen, wenn ihr euch den Code mal ansehen könntet und mir zeigen, was ich verändern muss damit es läuft 🙂
    Danke
    David

    PS:

    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    Thread *Insthread;
    int speed=0;
    boolean rechts=false;
    boolean links=false;
    Graphics::TBitmap * hintergrund = new Graphics::TBitmap;
    Graphics::TBitmap * buffer = new Graphics::TBitmap;
    Graphics::TBitmap * bild = new Graphics::TBitmap;
    
    Thread * Thread1 = new Thread(true);
    
    __fastcall Thread::Thread(bool CreateSuspended)
            : TThread(CreateSuspended)
    {
    
    }
    void __fastcall Thread::Execute()
    {
       int posx=0;
       int posy=400;
       int a=0;
       hintergrund->LoadFromFile("bild2.bmp");
       bild->LoadFromFile("bild.bmp");
       try
       {
          while(a<1000)
          {
                   buffer->Width=1000;
                   buffer->Height=1000;
                   bild->Transparent=true;
                   bild->TransparentColor=bild->Canvas->Pixels[0][0];
                   buffer->Canvas->Draw(0,0,hintergrund);
                   buffer->Canvas->Draw(posx,posy,bild);
                   Form1->Canvas->Draw(0,0,buffer);
                   Sleep(1);
                    a++;
                   if(rechts==true)
                   {
                      posx=posx+speed;
                      speed++;
                      if(speed>=3)
                         speed=3;
                   }
                   if(links==true)
                   {
                      posx=posx-speed;
                      speed++;
                      if(speed>=3)
                         speed=3;
                   }
          }
       }
                   catch(Exception &E)
                {
    
                }
    }
    
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    
    }
    void __fastcall TForm1::FormActivate(TObject *Sender)
    {
       Insthread= Thread1;
       Thread1->Resume();
       Form1->Height = 600;
       Form1->Width= 900;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       Form1->Caption=links;
       if(Key==37)
       {
          rechts=false;
          links=true;
          speed=0;
       }
       if(Key==39)
       {
           rechts=true;
           links=false;
           speed=0;
       }
       if(rechts==true && links==false)
          bild->LoadFromFile("bild3.bmp");
       if(links==true && rechts == false)
          bild->LoadFromFile("bild.bmp");
    
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       rechts=false;
       links=false;
       speed=0;
    }
    //---------------------------------------------------------------------------
    


  • Wie wärs, wenn du die Bilder nur einmal beim Start lädst und nicht jedesmal neu. Dann zeigst du halt bei Bedarf das jeweils richtige an. Mach die Bitmaps zu Membervariablen deiner Threadklasse. Das new kommt dann in den Konstruktor und ein dazugehöriges delete in den Destruktor. Entferne überhaupt alle globalen Variablen.



  • genau und gegen das flimmer kann man im notfall auch noch was mit doublebuffered anfangen (oder ähnlich fkt)



  • Mein neuer Quelltext sieht nun folgendermaßen aus:

    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    Thread *Insthread;
    int speed=0;
    boolean rechts=false;
    boolean links=false;
    Graphics::TBitmap * hintergrund = new Graphics::TBitmap;
    Graphics::TBitmap * buffer = new Graphics::TBitmap;
    Graphics::TBitmap * bild = new Graphics::TBitmap;
       int posx=0;
       int posy=400;
    
    Thread * Thread1 = new Thread(true);
    
    __fastcall Thread::Thread(bool CreateSuspended)
            : TThread(CreateSuspended)
    {
    
    }
    void __fastcall Thread::Execute()
    {
          while(!Thread1->Terminated)
          {
                   buffer->Width=1000;
                   buffer->Height=1000;
                   bild->Transparent=true;
                   bild->TransparentColor=bild->Canvas->Pixels[0][0];
                   buffer->Canvas->Draw(0,0,hintergrund);
                   buffer->Canvas->Draw(posx,posy,bild);
                   Form1->Canvas->Draw(0,0,buffer);
                   Sleep(1);
                   if(rechts==true)
                   {
                      posx=posx+speed;
                      speed++;
                      if(speed>=3)
                         speed=3;
                   }
                   if(links==true)
                   {
                      posx=posx-speed;
                      speed++;
                      if(speed>=3)
                         speed=3;
                   }
          }
    }
    
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    
    }
    void __fastcall TForm1::FormActivate(TObject *Sender)
    {
       Insthread= Thread1;
       Thread1->Resume();
       Form1->Height = 600;
       Form1->Width= 900;
       hintergrund->LoadFromFile("bild2.bmp");
       bild->LoadFromFile("bild.bmp");
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       Form1->Caption=links;
       if(Key==37)
       {
          rechts=false;
          links=true;
          speed=0;
       }
       if(Key==39)
       {
           rechts=true;
           links=false;
           speed=0;
       }
       if(rechts==true && links==false)
          bild->LoadFromFile("bild3.bmp");
       if(links==true && rechts == false)
          bild->LoadFromFile("bild.bmp");
    
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       rechts=false;
       links=false;
       speed=0;
    }
    //---------------------------------------------------------------------------
    

    Leider bleibt das Spiel nach einer Sekunde irgendwie stehn und wenn ich das sleep rausmache kommt direkt der Fehler, "OutofResources" obwohl der RAM nun leer genug bleibt und die Bitmaps außerhalb des Threads geladen werden...



  • Ich bin ja nicht so der Thread-Experte, aber sollte nicht auf Objekte, die nicht Member des Thread sind, mit Hilfe von Synchronize() zugegriffen werden?



  • Es muß nicht unbedingt Synchronize sein, aber auf jeden Fall müssen Daten, die sowohl von Form1, als auch vom Thread verwendet werden (in diesem Fall die ganzen globalen Variablen) über ein CriticalSection, oder einen Mutex geschützt werden.
    Da ein Teil der Variblen nur in Form1 gesetzt wird und im Thread nur gelesen werden, bietet sich hier ein TMultiReadExclusiveWriteSynchronizer-Objekt an.

    Auch darfst Du NICHT aus dem Thread heraus, direkt auf den Canvas von Form1 zeichnen. Auch hier muss ein möglicher gleichzeitiger Zugriff unterbunden werdne.



  • oha- ich werd mir das mal genauer angucken



  • Nicht unbedingt. Synchronize synchronisiert den Thread mit dem Hauptthread, d.h. der thread wird angehalten, bis die darin aufgerufenen Routine beendet ist. Das ist nur notwendig, wenn was im Hauptthread geändert werden soll.
    @777
    Was haben denn die TForm1 Funktionen hier zu suchen?? Du solltest deine Bilder im Konstruktor von Thread erzeugen und laden. Warum hast du zwei verschiedenen Variablen vom Typ Thread (Thread1 und Insthread)?

    __fastcall Thread::Thread(bool CreateSuspended)
            : TThread(CreateSuspended)
    {
      hintergrund = new Graphics::TBitmap;
      buffer = new Graphics::TBitmap;
      bild = new Graphics::TBitmap;
      hintergrund->LoadFromFile("bild2.bmp");
      bild->LoadFromFile("bild.bmp");
    // usw.
    }
    
    //dann Destruktor
    __fastcall Thread::~Thread()
    {
      delete hintergrund;
      delete buffer;
      delete bild;
    }
    

    Dazu müssen die Bitmapinstanzen Membervariablen von Thread werden.
    Bitt schau dir nochmal ein Tutorial zum Thema objektorientierte Programmierung bzw. Klassen an.
    Ich hab heute leider nicht genug Zeit um das hier im Einzelnen durchzugehen.

    Ciao



  • Vielen Dank Leute- mein Programm läuft jetzt mit folgendem Code super 🙂

    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    Thread *Insthread;
    int speed=3;
    boolean rechts=false;
    boolean links=false;
    Graphics::TBitmap * hintergrund = new Graphics::TBitmap;
    Graphics::TBitmap * buffer = new Graphics::TBitmap;
    Graphics::TBitmap * bild = new Graphics::TBitmap;
       int posx=0;
       int posy=450;
    
    Thread * Thread1 = new Thread(true);
    
    __fastcall Thread::Thread(bool CreateSuspended)
            : TThread(CreateSuspended)
    {
    
    }
    void __fastcall Thread::Execute()
    {
       buffer->Width=1000;
       buffer->Height=1000;
    
      while(!Terminated)
      {
          Synchronize(syncro);
          Sleep(1);
      }
    }
    void __fastcall Thread::syncro()
    {
       bild->Transparent=true;
       bild->TransparentColor=bild->Canvas->Pixels[0][0];
       buffer->Canvas->Draw(0,0,hintergrund);
       buffer->Canvas->Draw(posx,posy,bild);
       Form1->Canvas->Draw(0,0,buffer);
    
       if(rechts==true)
       {
          posx=posx+speed;
       }
       if(links==true)
       {
          posx=posx-speed;
       }
    }
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    
    }
    void __fastcall TForm1::FormActivate(TObject *Sender)
    {
       Insthread= Thread1;
       Thread1->Resume();
       Form1->Height = 600;
       Form1->Width= 900;
       hintergrund->LoadFromFile("bild2.bmp");
       bild->LoadFromFile("bild.bmp");
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       Form1->Caption=Key;
       if(Key==16)
       {
          speed=6;
       }
       else
       {
          speed=3;
       }
    
       if(Key==37)
       {
          rechts=false;
          links=true;
       }
       if(Key==39)
       {
           rechts=true;
           links=false;
       }
       if(rechts==true && links==false)
          bild->LoadFromFile("bild3.bmp");
       if(links==true && rechts == false)
          bild->LoadFromFile("bild.bmp");
    
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
       rechts=false;
       links=false;
    }
    //---------------------------------------------------------------------------
    

Anmelden zum Antworten