Thread aus Tutorial
-
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.zipDanke 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 SImonP.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.
-
Update:
ich habe zum Spaß einfach nochmal ein Tutorial-Projekt erzeugt. Hat funktioniert.
Nachdem, ich den Inhalt der unit1.h in die unit1.cpp kopiert habe und unit1.h absolut auskommentiert habe, bekomme ich den Fehler wieder. Es liegt also doch daran, wo die Sachen untergebracht sind. Kann mir das jemand erklären? Ebenfalls funktioniert es nicht, alles ausd er unit1.cpp in die unit1.h zu kopieren und unit1.cpp auszukommentieren.
?
Non comprendre.Simon
-
Irgendwie verstehe ich dein Problem nicht so ganz.
In deinem Thread musst Du doch, vor allem für ein solch Simples Tutorial, nur den Header deiner Form1 einbinden. (Unit1.h)?
Form1->Caption = IntToStr(FCount);
Woher sollte er sonst Form1 kennen?
Execute() wenn Du dir einen Quelltext haltepunkt im Debugger setzt der nie erreicht wird, kann man zu 90% davon ausgehen das dieser Punkt auch nie erreicht wird
Wenn ich nicht gerade absolut auf dem Schlauch stehe wird Execute() erst ausgeführt, sobald Du nach der der Thread-Objekt deklaration auch noch Resume() aufrufst.
myThread th = new myThread(NULL); myThread->Resume();
Hoffe das ich nicht gerade am Thema vorbei schreibe aber der `Fred` hier ist etwas verwirrend!