Threadfunktion
-
Wie soll ich das denn mit den Flags genau machen?
Also ich habe in der Warten Funktion eine WaitFor, welche unendlich lange wartet, wenn keine Aktion geschieht.
Diesen Thread würde ich gerne auch killen können, durch z.B. einem Stop- Button.
Geht das mit der ID?
Und wenn ja, wie?Wegen den Fehlern:
... public: // User declarations unsigned __stdcall Warten(void*); __fastcall TForm1(TComponent* Owner); };__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ... _beginthreadex(NULL, 0, Warten, NULL, 0, &ThreadID); ... } unsigned __stdcall TForm1::Warten(void *) { ... }
-
Erstens: Callback-Mechanismen haben so ihre (hm) Probleme mit Klassenmethoden (da fehlt einfach der this-Zeiger) - nimm eine globale Funktion oder eine statische Methode.
Zweitens: Killen von außen ist schlecht. Beenden von innen ist besser:
class TForm1 { ... bool ende;//Endemarke für Thread static unsigned __stdcall Warten(void*);//Threadfunktion ... }; unsigned __stdcall TForm1::Warten(void *param) { TForm1* pthis = static_cast<TForm1*>(param); while(!pthis->ende) { ...//mach was } } __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner), ende(false) { ... _beginthreadex(NULL, 0, Warten, this, 0, &ThreadID); ... } int TForm1::OnButtonStop() { ende=true;//<- dadurch wird die Schleife in der Thread-Funktion SAUBER beendet }
-
Danke aber was genau soll
[C++ Error] Unit1.cpp(173): E2231 Member TForm1::FileListBox1 cannot be used without an object
heißen?
Denn diese Meldung erscheint nun...
-
Achso und gibt es denn eine Funktion, mit der man einen Thread mit Hilfe der ID killen kann??
-
TheCaleb schrieb:
Danke aber was genau soll
[C++ Error] Unit1.cpp(173): E2231 Member TForm1::FileListBox1 cannot be used without an object
heißen?
Denn diese Meldung erscheint nun...Dadurch, daß die Threadfunktion statisch ist, kann sie nicht mehr direkt auf "normale" Member zugreifen (eine Einschränkung gibt's immer). Also mußt du indirekt zugreifen über
pthis->FileListBox1.Und wenn du unbedingt den Thread von außen killen willst, nimm TeminateThread (mit dem Rückgabewert von _beginthreadex() als Thread-Handle).
Aber auch auf die Gefahr hin, mich zu wiederholen: TU'S LIEBER NICHT. Auf diese Weise wird der Thread SOFORT abgeschossen, ohne die Chance auf irgendwelche Aufräumarbeiten. Wenn du Glück hast, bleibt nur ein Speicherleck, aber mit etwas Pech blockierst du dir damit das gesamte Programm. Die bessere Lösung ist es, den Thread sanft einschlafen zu lassen (Code siehe oben) - das Hauptprogramm setzt 'ende' auf true und der Thread erkennt diese Änderung bei nächster Gelegenheit und beendet sich selbst (inklusive Aufräumarbeiten).
-
Ist ok, dann werde ich die sanfte Methode von dir einbauen!
Ähm wie kann ich denn diese this in
_beginthreadex(NULL, 0, Warten, this, 0, &ThreadID);und
TForm1* pthis = static_cast<TForm1*>(param);auf mehrere Funktionen anwenden??
Also die Warten Funktion ruft ein weitern Thread auf, wo die FileListBox1 gebraucht wird.Ich habe das nun so gemacht, doch das geht nicht:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ... _beginthreadex(NULL, 0, Warten, this, 0, &ThreadID); ... } unsigned __stdcall TForm1::Warten(void *param) { TForm1* pthis = static_cast<TForm1*>(param); ... _beginthreadex(NULL, 0, MoveFiles,pthis, 0, &ThreadID); } unsigned __stdcall TForm1::MoveFiles(void *param) { TForm1* pthis = static_cast<TForm1*>(param); ... pthis->FileListBox1->Update(); ... }
-
Bist du sicher, daß es nötig ist, so mit Threads um sich zu werfen?
-
Ja ich brauche mehrere Threads!
Wie mache ich das denn, dass ich dem anderen Thread ebenfalls einen Zufgiff auf die FileListBox1 geben kann, ohne ein Fehler zu erzeugen?
-
Wenn es dir nur um den Compiler geht, ist das oben der richtige Weg. Allerdings kenne ich es zumindest von MFC, daß du nicht Thread-übergreifend auf Fenster und Dialogitems zugreifen kannst (wie das bei Borland aussieht, mußt du die Experten fragen). D.h. die Arbeitsthreads sollten per SendMessage() eine Nachricht an den Haupt-(=Anzeige-)Thread senden, der sich dann um die Darstellung kümmern kann.
-
EIgentlich hat es nichts mit MFC oder Borland zu tun, sondern *darf* aus Gründen der WinAPI nicht Thread-übergreifend auf andere Fenster zugreifen!
Bei einigen Nachrichten geht es wohl (zufällig), aber ob dies in Vista oder späteren OS-Version der Fall ist, ist MS überlassen. Es ist dokumentiert, dass man es nicht *darf* (kann gerade nur die Stelle nicht finden
)
-
Es geht bei mir da drum, dass die FileListBox1 vom Thread aus geupdatet werden muss und ich Strings und den Count von dieser benötige, doch weiß ich halt leider nicht, wie ich das erreichen kann, da mir dann Borland eine Fehlermeldung entgegen wirft, vonwegen dass ich nicht den CoInitializer durchgeführt habe oder so ähnlich!
-
Ok, also ich habe in dem Warten Thread das Update von der FileListBox gemacht, kein Problem, doch wenn ich in diesem Thread einen weiteren Thread, wie folgt aufrufen lasse, tritt der Fehler auf!
_beginthreadex(NULL, 0, MoveFiles,&FileL, 0, &ThreadID);
-
Der Fehler lautet: Project ... raised exception class EOleSysError with message 'CoInitialize wurde nicht aufgerufen'. Process stopped. Use Step or Run to continue.
-
Ich brauche immer noch Hilfe!
Hat Keiner eine Idee??
-
TheCaleb schrieb:
Der Fehler lautet: Project ... raised exception class EOleSysError with message 'CoInitialize wurde nicht aufgerufen'. Process stopped. Use Step or Run to continue.
Und? Was sagt dieser Fehler: 'CoInitialize wurde nicht aufgerufen'
Ist das so schwer? Ruf diese Funktion auf. In der MSDN steht genug dazu Dir zu erklären warum das notwendig ist.Solche Fragen zu posten finde ich schon albern.
Just my 2 cents
-
Ok mein Fehler!
Vielleicht habe ich mich falsch ausgedrückt, denn diesen CoInitialize habe ich schonmal ausgeführt, doch dann kommt folgende Meldung:Project ... raised exception class EAccessViolation with message 'Access violation at adress 004344B8. Read of adress 7020769'. Process stopped. Use Step or Run to continue.
Ich hatte das mit dem CoInitialize geschrieben, da ich mir dachte, dass ich da irgendwas anderes falsch mache, anstatt nicht den CoInitialize auszuführen.
Bzw ich gehe davon aus, dass ich diese Funktion garnicht ausführen muss, sondern das ich was anderes machen muss!Ich beschreibe einfach mal mein Problem, vielleicht ist es dann besser ersichtlich, was ich vor habe:
Ich möchte gerne ein Thread erstellen, welcher auf Funktionen des Hauptthreads zugreifen kann, wie z.B. auf die grafischen Objekte.
Um genau zu sein möchte ich ein Thread erstellen, welcher einen anderen Thread erzeugt und dieser andere Thread braucht die Funktionen des Hauptthreads und zusätzlich noch XML- und File- Funktionen.
Wobei die grafischen Objekte z.B. die FileListBox nutze ich nur um an Dateinamen aus einem Ordner zu gelangen, da ich sonst kein Weg gefunden habe.
Also um die Funktion dieses Threads kurz mal zu erläutern der Thread läd ein XML- Dokument und speichert jede verschobene Datei in diesem Dokument. Zusätzlich überprüft der Thread ob diese Datei, die er verschieben soll, schon dokumentiert ist und löscht diese, falls ein Eintrag existiert.
-
Funktionen sind nicht das Problem. Sondern die daten und Objekte. Es gibt sogenannte Threadafinitäten, das bedeutet man kan nicht einfach aus jedem Thread jedes Objekt wahlfrei verwenden.
Dein Konzept sehe ichals unstrukturiert und auch nicht als vernüftig an.
Denk Dir Threads bitte einfach als begrenzte Arbeiterklassen.
Diese sollten auf so wenig Funktionen und Daten und Objekte zugreifen wie möglich. Schon gar nicht sollten GUI und Fenster über threadgrenzen behandelt werden!Ich verstehe vor allem nicht was Du Dir von einem multithreading Konzept als Vorteil erwartest. Was Du schilderst wird durch MT nur kompliziert und fehleranfällig!
-
Hm ist ok, kann ich denn mit einem Thread eine Funktion des Hauptthreads aufrufen, Welche dann ein paar Aufgaben macht und anschließend vielleicht ein anderen Thread aufruft??
Bzw ich überlege mir ein Wartethread zu erzeugen, welcher bei einer Aktion eine Funktion des Haupttheads aufruft, die dann halt die Überprüfung und so macht und anschließend sollt dann ein anderer Thread das Verschieben übernehmen.
Ist das so möglich??Bzw ich möchte mit den Threads erreichen, dass ich die Oberfälche des Programms weiterhin nutzen kann, wenn es z.B. am arbeiten ist.
Und die Warte und Verschiebfunktion würde das benutzen er Oberfläche stören, wenn alles vom Hauptthread gemacht würde.
-
Bevor du dir weitere Gedanken machst, solltest du dich erst einmal informieren, was ein Thread überhaupt ist
(vor allem haben Threads keine "Funktionen")In deinem Fall sieht es so aus: Der Hauptthread kümmert sich um die Kommunikation mit dem User (Bildschirmdarstellung und Entgegennahme von Eingaben). Einen Warte-Thread daneben brauchst du nicht wirklich - der Hauptthread ist schon selber ständig im Wartezustand.
Ein Arbeitsthread, der sich um langwierige Aufgaben (wie das Verschieben) kümmert, ist schon sinnvoll. Dieser wird als Reaktion auf einen Tastendruck gestartet und kann wiederum per PostMessage() Nachrichten an den Hauptthread senden, wenn er etwas wichtiges zu sagen hat. Der Hauptthread verarbeitet diese Nachrichten dann auf normalem Weg mit und kümmert sich zum Beispiel darum, die Statusmeldungen des Threads auf dem Monitor darszustellen (umgekehrt kann er auch den Abbrechen-Button auswerten und dem Arbeitsthread sagen, daß er sich beenden soll).
-
Hmmmmm also wenn ich alles von einer Funktion ausführen lasse, dann muss ich ja nen Timer setzen, der nach einer bestimmten Zeit immer eine Funktion durchläuft oder wie soll ich das machen???
Denn irgendwie muss ich doch gucken, ob der Wartethread mit der WaitFor... Funktion eine Aktion gefunden hat, oder??