Frage bezüglich gleichzeitigem Aufruf mehrerer Methoden



  • Hallo zusammen,
    ich habe eine Methode, die einfach nur hintereinander verschiedene Bilder auf einem Image darstellen soll. Die geschieht solange, bis ein Parameter auf false gesetzt wird (ich verwende Application.ProcessMessages()).

    Nun ist mein Problem, dass ich genau 3 Images habe und für alle drei gleichzeitig die gleiche Methode ausgeführt werden soll. Ich übergebe den Imagenamen per Parameter.

    Das Problem ist nun, dass das Problem solange im ersten Aufruf der Methode bleibt, bis diese mit dem false-Parameter unterbrochen wurde. Erst dann startet der zweite Aufruf. Das ist ja auch verständlich. Ich frage mich aber, ob ich dieses Problem auch lösen kann, sodass alle drei Methoden gleichzeitig abgearbeitet werden.

    So sieht die ziemlich einfache Methode aus:

    void TVisual.turn_pic(TImage image, bool a)
    {
     while(a) 
     {
      Application->ProcessMessages();
      sleep(500);
      image->Picture->LoadFromFile("C:\...\Zahl1.bmp");
      Application->ProcessMessages();
      sleep(500);
      image->Picture->LoadFromFile("C:\...\Zahl2.bmp");
      Application->ProcessMessages();
      sleep(500);
      image->Picture->LoadFromFile("C:\...\Zahl3.bmp");
      Application->ProcessMessages();
      sleep(500);
      image->Picture->LoadFromFile("C:\...\Zahl4.bmp");
      Application->ProcessMessages();
      sleep(500);
      image->Picture->LoadFromFile("C:\...\Zahl5.bmp");
     }
    }
    //Diese Mehtode soll dreimal gleichzeitig aufgerufen werden, da drei Images gleichzeit bearbeitet werden sollen.
    

    Könnt ihr mir helfen?

    Vielen Dank
    lg, freakC++

    PS.: Ist "sleep()" eigentlich deprecated?



  • 557 Posts und noch nichts von Threads gehört? Kann ich ja fast nich glauben. Drei Timer wären eine andere Möglichkeit.

    greetz KN4CK3R



  • Hallo,
    tja, man sollte halt nie nach Posts urteilen!!! Wenn man sich eine Programmiersprache ohne jegliche Vorkenntnisse ohne irgendwelche Hilfe im stressigen Schulalltag beibringt, da fallen dann schonmal ein paar Fragen an, die ich dann regelmäßig in diesem Forum stelle.

    Außerdem nutze ich eher selten Borland.

    Zwar habe ich schon von Threads gehört, aber diese noch nie angewandt. Ich habe das Problem mit deinem Vorschlag gelöst.

    Naja, vielen Dank für deinen Tipp!

    lg, freakC++



  • Application->ProcessMessages() ist böse, sogar richtig böse. Du musst haargenau wissen, was du wann machst, ansonsten fliegt dir deine Anwendung um die Ohren.
    Im Grund brauchst du soagr nur einen Timer, es sei denn, die drei Bilder sollen unterschiedlich schnell aktualisiert werden.
    Ausserdem solltest du die Bilder zwischenspeichern, damit sie nicht jedes Mal neu eingeladen werden müssen. Ansonsten kannst du den Timer gleich weglassen :p.

    Nimm einen std::vectorTGraphics::TBitmap* (noch besser: std::vector<boost::shared_ptrTGraphics::TBitmap* > oder boost::ptr_vectorTGraphics::TBitmap) und lade alle Bilder dort hinein, dann musst du dir beim Zeichnen nur noch den Index des anzuzeigenden Bildes merken.



  • /OT: Da ich Application->ProcessMessages() nutze würde ich mal gerne wissen, was daran böse ist, bzw. was die Fallstricke sind.

    mfg
    xXx



  • Angenommen du hast ein Fenster, in dem du in einer Methode ein langwierige Berechnung durchführst und deswegen zwischendurch Application->ProcessMessages aufrufst. Application->ProcessMessages bearbeitet dann unter anderem die Windows Nachrichten des aktuellen Fensters und kehrt dann in die aufrufende Methode zurück. Wenn der Benutzer das Fenster schliesst, während die Berechnung noch läuft, ist das Fensterhandle nicht mehr gültig oder das Fensterobjekt existiert nicht mehr:

    void Form1::OnClickBtnStart( TObject* Sender )
    {
       // Frame erzeugen, der eine langwierige Aufgabe übernimmt
       // durch Verpacken in einen shared_ptr wird das Worker Formular
       // nach Beenden automatisch zerstört und dessen Resourcen wieder
       // freigegeben
       boost::shared_ptr<TForm2> WorkerForm( this );
       WorkerForm->ShowModal();
    }
    
    void WorkerForm::DoWork()
    {
       for( int x = 1; x < GANZGANZGANZVIEL; ++x )
       {
          berechne_was_fürchterlich_komplexes();
          Application->ProcessMessages();
       }
    }
    

    Wenn der Benutzer im obigen Beispiel das WorkerFrame schliesst, während die Schleife noch nicht abgearbeitet wurde, passiert folgendes:

    1. WM_CLOSE wird in die Nachrichten Queue des WorkerFrame eingefügt
    2. Application->ProcessMessages findet WM_CLOSE und schliesst daraufhin das WorkerFrame
      2a) Der Main Thread kehrt in Form1::OnClickBtnStart() zurück, da das WorkerFrame geschlossen worden ist.
      2b) der shared_ptr verlässt den scope und zerstört das WorkerFrame mitsamt allen Resourcen
      2c) restliche Windows Queue wird abgearbeitet
      2d) Application->ProcessMessages() kehrt nach WorkerForm::DoWork() zurück, weil alle Nachrichten abgearbeitet sind
    3. Es gibt kein gültiges Objekt mehr, auf dem WorkerForm::DoWork() arbeiten kann => Undefiniertes verhalten => Viel Glück


  • DocShoe schrieb:

    Application->ProcessMessages() ist böse, sogar richtig böse. Du musst haargenau wissen, was du wann machst, ansonsten fliegt dir deine Anwendung um die Ohren.

    Eine überaus angebrachte Warnung.

    Neben dem WM_CLOSE-Szenario, das du erwähnst, kann es ja immer passieren, daß ein anderer deiner Event-Handler aufgerufen wird. Und das geht nur dann unfallfrei, wenn dein Code sowie aller VCL-Code, der implizit aufgerufen wird, wiedereintrittsfest ist.



  • Okay, das habe ich intuitiv richtig gemacht.
    Ich benutze das um in modalen Fenstern die Statusbar zu aktualisieren. Da kann der Nutzer eh keine Events (jenseits von MouseMove etc) auslösen, auch nicht das Fenster zu schließen...

    mfg
    xXx


Log in to reply