TThread läuft nicht Planmäßig



  • Hallo Community,

    ich benutze ein TThread, welches ich von einem TForm aus Aufrufe.
    Nur leider werden in der Execute() Funktion vom TThread keine TForm Eigenschaften bzw. deren Objekte geändert.

    Anbei Code-Auszüge

    unit1.cpp

    void __fastcall TFrmMain::FormShow(TObject *Sender)
    {
      [...]
                    TimerFoundSrcPre->Enabled = true ;
    
                    FindSourcesThread = new TFoundSrcPreThread(true) ;
                    FindSourcesThread->OnTerminate = DeleteFindSourcesThread ;
                    FindSourcesThread->Resume() ;
    }
    
    void __fastcall TFrmMain::TimerFoundSrcPreTimer(TObject *Sender)
    {
            TestLbl->Caption = TestLbl->Caption + "1 " ;
    }
    
    void __fastcall TFrmMain::DeleteFindSourcesThread(TObject *Sender)
    {
            FindSourcesThread->Terminate() ;
    }
    

    FindSourceThread.cpp

    void __fastcall TFoundSrcPreThread::Sync()
    {
            FrmMain->TimerFoundSrcPre->Enabled = false ;
    
            FrmMain->Caption = "Test" ;
            Application->Title = "Hello" ;
    }
    
    __fastcall TFoundSrcPreThread::TFoundSrcPreThread(bool CreateSuspended)
            : TThread(CreateSuspended)
    {
            this->FreeOnTerminate = true ;
    }
    
    //---------------------------------------------------------------------------
    void __fastcall TFoundSrcPreThread::Execute()
    {
            FrmMain->FindSources(
                                  FrmMain->slTargetList,
                                  FrmMain->strDestinationDir,
                                  true
                                ) ;
    
            Synchronize(&Sync) ;
    
            FrmMain->Caption = "Test" ;
            FrmMain->TimerFoundSrcPre->Enabled = false ;
    }
    

    Also nach dem ausführen des Programms, wird der Title der Application umgeschrieben auf "Hello" und die Einsen wandern. 😉

    Nur sollte ja eigentlich der Timer abgeschaltet sein und das Form eine andere Caption haben. Leider funktioniert es nicht und die Passagen werden durchlaufen, was ich durch Haltepunkte getestet habe.
    Ich sehe wohl den Wald vor lauter Bäume nicht mehr. 🙄

    Hat einer von Euch noch eine Idee?

    Beste Grüße,
    Trawler



  • Bei Wenn du mit einem Thread auf VCL objekte zugreifen willst, musst du den Thread erst mit der Form Synchonsieren.

    Wenn du ein Thread Objekt erstellst, steht oben folgendes drüber:

    //   Important: Methods and properties of objects in VCL can only be
    //   used in a method called using Synchronize, for example:
    //
    //      Synchronize(&UpdateCaption);
    //
    //   where UpdateCaption could look like:
    //
    //      void __fastcall ThreadStation3::UpdateCaption()
    //      {
    //        Form1->Caption = "Updated in a thread";
    //      }
    //---------------------------------------------------------------------------
    

    Das hatte ich anfangs auch immer vergessen und das führt zu echt lustigen verhalten.



  • Soweit ich sehe, kennt dein Thread FrmMain garnicht. Deshalb kann er da auch nichts verändern. Dass das Programm trotzdem läuft ist mMn ziemliches "Glück". Weise FindSourcesThread->FrmMain vor Resume() die korrekte Adresse zu.

    Und wie Fragemann123 schrieb, musst du alle Aufrufe von VCL-Funktionen über Synchronize() kapseln, auch FrmMain->FindSources().

    Du rufst in OnTerminate des Threads über DeleteFindSourcesThread() wieder Terminate() auf. Das ist nutzlos. Dein Thread kann gar nicht auf Terminate() reagieren, weil es in Execute() nicht geprüft wird. DeleteFindSourcesThread() müsste übrigens TerminateFindSourcesThread() heißen.

    Du solltest wahrscheinlich FrmMain->FindSources() in den Thread verlagern und alle benötigten Variablen an den Thread übergeben. Die einzige Arbeitsfunktion des Threads in Synchronize() zu packen, ist albern.



  • @Poster: Erst mal vielen Dank für das Feedback und die Hinweise.
    Mit DeleteFindSourcesThread stimmt es natürlich von der Benennung. Habe es nur von dem Tutorial übernommen: VCL-Thread

    Nun aber wieder zu den Fakten:
    FrmMain->FindSources() wird in Execute() ausgeführt und arbeitet auch soweit korrekt. Eine Verschiebung nach TFoundSrcPreThread::Sync() hat jedoch auch nix gebracht. FrmMain->Caption bleibt leider komplett unverändert.

    FrmMain sollte eigentlich dem Thread bekannt sein, da ich die Header-Datei unit1.h einbinde. Hätte ich vielleicht in meinem Code mit aufnehmen sollen. Oder meinst Du es mit dem Bekanntmachen noch anders?

    @Fragemann123: Die Funktion TFoundSrcPreThread::Sync() sollte eigentlich genau dies sein, was Du mit Deinem Code meinst.



  • Schmeiss am besten mal diese Zeilen aus der Execute Methode heraus, die rufst du ja eh in der Sync Methode auf, und da ist es auch richtig:

    [code]
            FrmMain->Caption = "Test" ;
            FrmMain->TimerFoundSrcPre->Enabled = false ; 
    [/code]
    

    Hier können nämlich immer noch einige "Schweinereien" auftreten.



  • Was ein weiterer Aufruf in der project.cpp alles für folgen haben kann.

    Application->CreateForm(__classid(TFrmMain), &FrmMain);
    

    Nur weiß ich nicht wie er dahin gekommen ist. Aber zur Info: Ob in Sync() oder Execute() es funktioniert beides. Habe es aber dennoch nach Sync() verlagert.

    Vielen Dank Euch allen.


Anmelden zum Antworten