Threadfunktion
-
Vielen Dank, doch wie kann ich den mit _beginthreadex erzeugten Thread wieder killen?
Bei CreateThread wurde ja ein Handle zurück gegeben mit dem das ging, oder irre ich mich da??
-
Und wenn ich die Funktion mit
unsigned __stdcall Warten(void*);deklariere und die alles andere nach CStolls Beispiel mache, meldet mir der Compiler:
[C++ Error] Unit1.cpp(82): E2034 Cannot convert 'unsigned int (__stdcall * (_closure )(void *))(void *)' to 'unsigned int (__stdcall *)(void *)'
[C++ Error] Unit1.cpp(82): E2342 Type mismatch in parameter '__start' (wanted 'unsigned int (__stdcall *)(void *)', got 'void')
-
TheCaleb schrieb:
Und wenn ich die Funktion mit
unsigned __stdcall Warten(void*);deklariere und die alles andere nach CStolls Beispiel mache, meldet mir der Compiler:
[C++ Error] Unit1.cpp(82): E2034 Cannot convert 'unsigned int (__stdcall * (_closure )(void *))(void *)' to 'unsigned int (__stdcall *)(void *)'
[C++ Error] Unit1.cpp(82): E2342 Type mismatch in parameter '__start' (wanted 'unsigned int (__stdcall *)(void *)', got 'void')
Zeige uns doch einfach Code. Das ist so einfach nur fischen im Trüben. Ichhabe das Gefühl Du hast wieder einen Adressoperator zuviel!
-
TheCaleb schrieb:
Vielen Dank, doch wie kann ich den mit _beginthreadex erzeugten Thread wieder killen?
Bei CreateThread wurde ja ein Handle zurück gegeben mit dem das ging, oder irre ich mich da??Man killt keinen Thread! Ein Thread beendet sich, indem er einfach returniert!
Und das erreicht man einfach in dem man ein Flag/Event setzt un der Thread dieses Flag/Event erkennt und einfach returniert.
-
TheCaleb schrieb:
Vielen Dank, doch wie kann ich den mit _beginthreadex erzeugten Thread wieder killen?
Bei CreateThread wurde ja ein Handle zurück gegeben mit dem das ging, oder irre ich mich da??Ganz einfach: der letzte Parameter von beginthreadex ist ein Zeiger auf eine unsigned-Variable - dort packt die Funktion deine Thread-ID rein.
(aber es ist sowieso keine gute Idee, einen Thread von außen zu killen. Schick ihm lieber eine Nachricht, daß er sich beenden soll (du könntest z.B. einen Member der ThData-Struktur als Ende-Flag setzen))Zu der Fehlermeldung: Dann hast du es offenbar nicht so gemacht wie oben - zeig doch mal den genauen Code.
-
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