Thread aus Tutorial



  • Hallo CBuilder Gemeinde,

    ich bin noch Anfänger und versuche mich gerade an dem Tutorial
    http://bcb-tutorial.c-plusplus.net/Thread/artikel5.html
    Jedoch bekomme ich es nicht damit zu Laufen, es wird nichts an das
    Label im Form übergeben.
    Ich habe es mal so versucht:

    void __fastcall TMyThread::Execute()
    {
      Form1->Label2->Caption = "Hallo Welt"; 
      FCount = 1;
      do
      {
        Synchronize(&GuiElements);
        FCount++;
      }
      while (FCount <= 200000);
    }
    

    Es kommt schon das "Hallo Welt" nicht auf Label2 an.
    Label1 soll hier übergeben werden:

    void __fastcall TMyThread::GuiElements()
    { //Da wir uns nicht im Gültigkeitsbereich von Form1 befinden, müssen wir qualifizieren mit Form1.
        Form1->DisplayLabel->Caption = IntToStr(FCount);
    }
    

    Kann es sein das diese Zeile zum starten des Thread nicht ausreicht oder fehlt noch etwas?

    void __fastcall TForm1::StartThreadButtonClick(TObject *Sender)
    {
      new TMyThread(false);
    }
    

    Danke schon mal für die Hilfe
    Gruß Sascha



  • Hallo

    Benutz den Debugger um zu überprüfen ob deine Thread-Routine überhaupt erreicht wird.
    Der Aufruf zum erstellen von TMyThread ist soweit in Ordnung, natürlich sehen wir hier nicht wie der Konstruktor von TMyThread konkret bei dir implementiert ist.

    bis bald
    akari



  • Danke erst mal, habe ich gemacht!
    Es kommt eine ID der Zustand geht dann auf Angehalten und Status Init.
    Nach einigen Sekunden wechselt der Status auf unbekannt.
    Was wohl bedeutet das die Methode:
    void __fastcall Updater_Thread::Execute() niemals ausgeführt wird.
    Aber was mache ich nun?



  • Ich habe in den Tut. jetzt mal das versucht:

    void __fastcall TForm1::StartThreadButtonClick(TObject *Sender)
    {
      FNewThread = new TMyThread(false); //Jetzt haben wir eine in der ganzen Klasse sichtbare Instanz.
      FNewThread->OnTerminate = DeleteThread;
    }
    

    Das Ergebnis ist:
    [C++ Fehler] Unit1.cpp(011): E2451 Undefiniertes Symbol 'FNewThread'
    [C++ Fehler] Unit1.cpp(012): E2451 Undefiniertes Symbol 'DeleteThread'



  • Hallo

    Es reicht nicht einfach irgendwo irgendwas rauszukopieren, du must es auch verstehen.
    Und auch die Fehlermeldungen sind sehr gut verständlich, FNewThread und DeleteThread sind nicht bekannt weil du sie nirgends deklariert hast. Schau nochmal in das Tutorial, dort werden sicher die notwendigen Deklarationen (und Implementationen) stehen.

    bis bald
    akari



  • du hast vergessen die Variable 'FNewThread' und den Funktionsprototyp von 'DeleteThread' in den Header zu schreiben (in die Klasse)

    lad dir doch einfach mal das fertige Projekt zum Tutorial runter

    [Edit]

    akari schrieb:

    Schau nochmal in das Tutorial, dort werden sicher die notwendigen Deklarationen (und Implementationen) stehen.

    steht (leider) nicht so ausführlich drin. wahrscheinlich setzt das Tutorial schon einige Grundkenntnisse der Programmierung mit dem BCB voraus, was ja bei dem Thema auch kein Wunder ist



  • Gut, danke das habe ich dann auch gefunden und kapiert.
    Soweit klappt das auch, nur kann ich das auch mit einem modalen Fenster machen und nicht nur auf dem Hauptform?



  • Hallo

    Selbstverständlich kannst du auch jedes anderes Form dafür verwenden, du must den Code nur entsprechend abändern.

    bis bald
    akari



  • Also ich habe noch einige Versuche gemacht, aber in einem modalen Fenster wird der Label einfach nicht aktualisiert.
    Wenn jemand Zeit und Lust hat, ich habe das Demoprojekt hier mal raufgeladen:
    http://www.muellordner.kilu.de/bsp/bsp_thread.zip

    Danke nochmal



  • Hat wirklich keiner eine Idee, warum der Label in dem modalen Fenster nicht aktualisiert wird?



  • Ok, ein paar Dinge sind mir in dem Projekt aufgefallen.

    Die Funktion TForm1::DeleteThread() wird aufgerufen, sobald der Thread terminiert wird, den Thread dort erneut zu terminieren ist schlicht und ergreifend sinnlos. Kann unter Umständen auch zu Problemen führen. Diese DeleteThread-Funktion kannst Du also getrost entfernen.

    Dann können mehrere Threads gestartet werden, aber es wird immer nur die letzte Instanz in FNewThread gespeichert. Solange die Threads automatisch termininiert werden (FreeOnTerminate = true), ist das aber kein Problem.

    Zu dem Problem mit dem modalen Fenster: Beim Programmstart wird eine Instanz des TForm3 namens Form3 automatisch erzeugt, aber nicht angezeigt. Diese nicht sichtbare Form aktualisierst Du aus dem Thread heraus, nicht jedoch die manuell erzeugte Instanz und angezeigte Instanz von TForm3. Wenn Du auf diese manuell erstellte Instanz zugreifen willst, musst Du dem Thread einen Zeiger auf diese Instanz übermitteln. Alternativ kannst du auch die automatisch erzeugte Instanz von TForm3 verwenden. Dazu musst Du folgendes ändern:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    //	TForm3 *F= new TForm3(Application);
    //	F->ShowModal();
    //	delete F;
    //	return; // braucht man in diesem Fall überhaupt nicht
    	Form3->ShowModal();
    }
    //---------------------------------------------------------------------------
    


  • Super Joe_M ,

    ich danke Dir es funktioniert. Habe bisher modale Fenster auf dem angewendeten Weg aufgerufen.

    Gruß Sascha



  • Hallo Leute,
    ich habe mir das Threads Turorial angesehen und durchgearbietet.
    (http://bcb-tutorial.c-plusplus.net/Thread/artikel5.html)
    Das hat sogar alles funktioniert wie es soll. Dann habe ich mein Programm weiter ausgebaut. Danach aber konnte ich nicht mehr auf die Elemente auf Form1 zugrifen, ich bekomme immer eine Zugriffsverletzung. Daraufhin habe ich meinen Code wieder soweit reduziert wie im Tutorial:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    
           new TReadComThread(false);
    }
    

    Im Header

    class TReadComThread : public TThread
    {
    private:
            //AnsiString Command;
            //TQueueThread *Q;
            //TUart *U;
            int FCount;
    
    protected:
            void __fastcall Execute();
            void __fastcall GuiElements();
    public:
            __fastcall TReadComThread(bool CreateSuspended);
    
    };
    
    __fastcall TReadComThread::TReadComThread(bool CreateSuspended)
        : TThread(CreateSuspended)
    {
        FreeOnTerminate = true;
    }
    
    void __fastcall TReadComThread::GuiElements()
    {
            //Da wir uns nicht im Gültigkeitsbereich von Form1 befinden, müssen wir qualifizieren mit Form1.
            Form1->Caption = IntToStr(FCount); [b]<- da tritt der fehler auf[/b]
    }
    
    void __fastcall TReadComThread::Execute()
    {
            FCount = 0;
            while (FCount < 1000)
            {
                    Synchronize(&GuiElements);
                    FCount ++;
    
            }
    }
    
    //---------------------------------------------------------------------------
    

    Ich habe sonst nix am laufen, keine OnCreate Routine oder sonstwas.
    Hat jemand eine Ahnung, waum ich so eine Zugriffsverletzung bekomme?
    Viele Grüße SImon

    P.S.: Sorry, dass ich den Artikel hier gepushed habe, das war ein totales Versehen.



  • Ist denn evtl. Form1 da nicht mehr gültig? Bist du mal mit dem Debugger durchgegangen (Breakpoint setzen)?



  • Hallo,
    also wenn Form1 dort nicht mehr gültig ist, müsste mir dann nicht der Compiler einen Fehler melden?
    Grüße Simon



  • Hallo

    Der Compiler würde einen Fehler bringen, wenn der Zeiger Form1 an der besagten Stelle nicht bekannt ist. Das ist ja nicht der Fall.
    Aber wenn zur Laufzeit der Zeiger auf einen Speicherbereich zeigt, in dem keine gültige Instanz liegt, dann kommt zur Laufzeit eine Zugriffsverletzung. Das meint Braunstein. Das könnte zum Beispiel passieren, wenn das Form schon geschlossen ist, aber der Thread immer noch läuft.

    bis bald
    akari



  • Aktiviere mal CodeGuard in den Projektoptionen; dann wirst du über falsche Speicherzugriffe benachrichtigt.



  • Hallo,
    danke zunächst schonmal für die Denkanstöße, ich bin nur leider im MOment nicht dazu gekommen das Problem anzugehen.
    Ich hab da aber noch eine Frage: so wie's im Tutorial steht hat es ja schon funktioniert. Ich habe dann allerdings das "Unit2.h" und "Unit1.cpp" aus dem Projekt entfernt und alles in eine eigene "hpp" Datei rein. Dabei habe ich ausser "#include <classes.hpp>" und außer den Klassendeklarationen etc nicht weiter übernommen. Könnte es auch damit was zu tun haben?
    Was das Debuggen etc angeht werde ich das mal durchführen sobald ich dazu zeit finde.
    Viele Grüße Simon



  • Hi,
    also ich habe über den Debugger mir jetzt den Haltepunkt gesetzt und mir dann Form1 ausgeben lassen. Woran kann ich jetzt erkennen, ob da der Wurm drin ist? Meinem Bauchgefühl nach ist da alles OK, weil eine Adresse hinterlegt ist (also nicht NULL) und weil sogar die Elemente auf Form1 im Objektinspektor angezeigt werden.
    Hat sonst jemand eine Idee, was da das Problem sein könnte? Sollte es einen Unterschied machen wo die Threadobjekte untergebracht sind? Eigentlich doch nicht oder?
    Grüße Simon



  • Edit: Unfug.


Anmelden zum Antworten