2 Fragen zu Threads
-
Hallo ihr,
also ich schau mir grad mal Threads an, hab mir zu testzwecken eine form mit 2 labels und 2 progressbars gemacht!
Auf buttonklick starten 2 threads die eben hochzählen und die progressbar updaten sollen:
TMyThread1.h:
#ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include <Classes.hpp> //--------------------------------------------------------------------------- class TMyThread1 : public TThread { private: protected: void __fastcall Execute(); int value; public: __fastcall TMyThread1(bool CreateSuspended); void __fastcall UpdateInstruction(); void __fastcall StartBar(); void __fastcall StepBar(); }; //--------------------------------------------------------------------------- #endifTMyThread1.cpp:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit2.h" #include "Unit1.h" #pragma package(smart_init) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- __fastcall TMyThread1::TMyThread1(bool CreateSuspended) : TThread(CreateSuspended) { } //--------------------------------------------------------------------------- void __fastcall TMyThread1::Execute() { value = 0; Synchronize(StartBar); do { Synchronize(UpdateInstruction); Synchronize(StepBar); value++; }while(value<100000); //---- Hier den Thread-Code plazieren---- } //--------------------------------------------------------------------------- void __fastcall TMyThread1::UpdateInstruction() { Form1->Edit1->Text = value; } void __fastcall TMyThread1::StartBar() { Form1->ProgressBar1->Min = 0; Form1->ProgressBar1->Max = 99999; } void __fastcall TMyThread1::StepBar() { Form1->ProgressBar1->Position=value; }TMyThread2.h:
//--------------------------------------------------------------------------- #ifndef Unit3H #define Unit3H //--------------------------------------------------------------------------- #include <Classes.hpp> //--------------------------------------------------------------------------- class TMyThread2 : public TThread { private: protected: void __fastcall Execute(); int value; public: __fastcall TMyThread2(bool CreateSuspended); void __fastcall UpdateInstruction(); void __fastcall StartBar(); }; //--------------------------------------------------------------------------- #endifTMyThread2.cpp
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit3.h" #include "Unit1.h" #pragma package(smart_init) const int MAX_VALUE = 99999; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- __fastcall TMyThread2::TMyThread2(bool CreateSuspended) : TThread(CreateSuspended) { } //--------------------------------------------------------------------------- void __fastcall TMyThread2::Execute() { value=0; Synchronize(StartBar); Sleep(200); do { Synchronize(UpdateInstruction); value++; }while(value<=MAX_VALUE); } //--------------------------------------------------------------------------- void __fastcall TMyThread2::UpdateInstruction() { Form1->Edit2->Text = value; Form1->ProgressBar2->Position = value; } void __fastcall TMyThread2::StartBar() { Form1->ProgressBar2->Min = 0; Form1->ProgressBar2->Max = MAX_VALUE; }TForm1.cpp
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #include "Unit3.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; TMyThread1 *mT1; TMyThread2 *mT2; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { mT1 = new TMyThread1(true); mT2 = new TMyThread2(true); mT1->Resume(); mT2->Resume(); } //---------------------------------------------------------------------------1 Frage(Problem): die Threads laufen los, und die Editfelder werden geupdatetet, aber irgendwann hört es auf mit updaten, und nur noch die progressbars laufen (so wie wenn man eine schleife ohne Application->ProcessMessages() macht) und die Editfelder werden erst am ende der threads aktualisiert (letzte zahl steht dann drin), woran liegt das?
2 Frage: wie oder wo beende (lösche) ich die Threads und gebe den Speicher wieder frei?
-
Hallo
den Thread kannst Du mit Terminate beenden.
Den Speicher musst Du entweder selber freigeben, oder er wird selber freigegeben. Schaue mal in der Hilfe nach FreeOnTerminate.Gruss
-
Du aktualisierst die Oberflächenelemente VIEL zu oft! Du darfst die Oberflächenelemente nicht bei jedem Durchlauf aktualisieren, sondern jeden hundertsten oder tausendsten Durchlauf.
Das Problem ist, dass die Synchronisierung mit Form1 extrem viel Zeit kostet. Und es kann auch immer nur ein Thread auf Form1 zugreifen. Du bremst Deine Threads aus. Du wirst feststellen, wenn Du die Aktualisierung nur jeden 1000sten Durchlauf machst, springen die Edits und Progressbars von 0 direkt auf den maximalen Wert.
Man verwendet Threads um Zeitintensive Berechnungen auszulagern, insofern ist Dein Beispiel ein bißchen ungünstig geraten, da es nichts anderes macht, als Oberflächenelemente auf Form1 zu aktualisieren. Aber genau das, sollte so selten wie möglich geschehen.
Wenn Du eine ProgressBar verwendest, macht es keinen Sinn den Max-Wert höher als 100 zu stellen. Und der Thread sollte die ProgressBar dann auch nur genau 100 Mal aktualisieren.
-
Man kann das auch gut Zeitgesteuert machen, indem man den Update der Oberfläche nur mit vl. 5 Hz ausführt...