Laufende Thread beenden??



  • Jochen Kalmbach schrieb:

    NIE Terminate/SuspendThread verwenden!

    es sei denn, man hat 'nen thread, der nur etwas berechnet, ohne jemals eine winapi- oder library-funktion aufzurufen...



  • Jochen Kalmbach schrieb:

    NIE Terminate/SuspendThread verwenden!

    es sei denn, man hat 'nen thread, der nur etwas berechnet, ohne jemals eine winapi- oder library-funktion aufzurufen...

    Naja...wenn der Thread Daten auf den Heap schaufelt, dann haste u.U. nette Memory Leaks, wenn Du TerminateThread aufrufst.

    Der Poster greift in seinem Thread auf GUI-Controls zu.

    p->SetWindowText(str);

    Das tut in den Augen weh und gehört verboten. Veränderungen an GUI-Komponenten immer mit PostMessage realisieren. Ausführliche Begründungen gibst wie immer bei Google.



  • wie kann ich über kontrols zugriefen mit postmessage?



  • Dies geschieht über Messages. Du kannst als Programmierer eigene Messagetypen definieren. Dein Haupt-Thread muss diese Message dann verarbeiten, um die GUI zu aktualisieren. Mit PostMessage versendet du dann deine selbstdefinierten Message asynchron aus deinem Workerthread heraus.

    Guck dir Progressbar-Artikel bei www.codeproject.com an.
    Bei Progressbars hast du auch die Situation, dass ein WorkerThread die GUI aktualisieren muss. Den ganzen Code mit Erklärungen kann ich hier nicht auf die Schnelle mal reinposten, zumal wurde das Thema schon mehrfach abgehandelt.

    Lies viel über nebenläufige Programmierung in C++. Das ist extrem wichtig, wenn du stabilen Code erzeugen willst. Das fiese an Threadprogrammierung ist, dass Fehler oft nicht zu reproduzieren sind. In 99,5% aller Fälle geht alles gut. Doch irgendwann kracht es oder zu hast nen Deadlock und du fragst dich wo zum Teufel dieser Crash verursacht wird. Die Suche nach solchen Fehler kann dich wochenlang beschäftigen.



  • DreiZweiEins schrieb:

    Dies geschieht über Messages. Du kannst als Programmierer eigene Messagetypen definieren. Dein Haupt-Thread muss diese Message dann verarbeiten, um die GUI zu aktualisieren. Mit PostMessage versendet du dann deine selbstdefinierten Message asynchron aus deinem Workerthread heraus.

    Guck dir Progressbar-Artikel bei www.codeproject.com an.
    Bei Progressbars hast du auch die Situation, dass ein WorkerThread die GUI aktualisieren muss. Den ganzen Code mit Erklärungen kann ich hier nicht auf die Schnelle mal reinposten, zumal wurde das Thema schon mehrfach abgehandelt.

    Lies viel über nebenläufige Programmierung in C++. Das ist extrem wichtig, wenn du stabilen Code erzeugen willst. Das fiese an Threadprogrammierung ist, dass Fehler oft nicht zu reproduzieren sind. In 99,5% aller Fälle geht alles gut. Doch irgendwann kracht es oder zu hast nen Deadlock und du fragst dich wo zum Teufel dieser Crash verursacht wird. Die Suche nach solchen Fehler kann dich wochenlang beschäftigen.

    👍
    Threads sind Die Hölle (tm).
    Das fieseste daran ist IMHO dass man erst merkt dass man nicht viel über Multithreading weiss, wenn man bereits viel mehr als der Durchschnittsprogrammierer über Multithreading weiss 🙂
    Oder anders gesagt: dass Leute die sich mit Multithreading nicht so auskennen oftmals glauben sie wüssten was sie tun. Was dann meistens ein Irrglaube ist.



  • ja ist ich weis hab schon oft gehört "vergiss threads, machs über timer"..

    aber ich will mich trozdem mal beschäftigen.. will 2 thread haben, und eine daten klasse... mit einem thread will ich die daten verändern (daten klasse) und mit dem andere trhead gleichzeitig die daten anzeigen bzw. lesen...

    vll. habt ihr ja schon bischen erfahrung und beispiel code



  • hustbaer schrieb:

    Threads sind Die Hölle (tm).
    Das fieseste daran ist IMHO dass man erst merkt dass man nicht viel über Multithreading weiss, wenn man bereits viel mehr als der Durchschnittsprogrammierer über Multithreading weiss 🙂
    Oder anders gesagt: dass Leute die sich mit Multithreading nicht so auskennen oftmals glauben sie wüssten was sie tun. Was dann meistens ein Irrglaube ist.

    jetzt übertreibst du aber....



  • wech: weil kein MFC



  • zhoosch, das tut echt in den Augen weh.
    Wenn du schon so einen Mist postest, dann schreib drüber, dass es Mist ist.



  • @zhoosch: Mein Beitrag auf Seite 1 hast Du wohl übersehen... Also nochmals für Dich: "Never ever use TerminateThread"!



  • DreiZweiEins schrieb:

    Der Poster greift in seinem Thread auf GUI-Controls zu.

    p->SetWindowText(str);

    Das tut in den Augen weh und gehört verboten. Veränderungen an GUI-Komponenten immer mit PostMessage realisieren. Ausführliche Begründungen gibst wie immer bei Google.

    Nun, da bin ich, auch wenn es unkonventionell erscheinen mag, durchaus anderer Meinung. Auch ich habe mal brav mit PostMessage(..) gearbeitet. Allerdings ist diese Funktion u.U. unzuverlässig und es geht schon mal die ein oder andere Nachricht, die via PostMessage(..) gesendet wurde, "verloren" 😞 . Bei kritischen Anwendungen, die wirklich alle Informationen aus einem Thread benötigen, ist das schon mal nicht sehr gut!
    Es geht auch ein SendMessage(..) oder eben auch ein direkter Zugriff. Natürlich immer unter der Voraussetzung, dass das ganze Projekt so implementiert ist, dass es sauber synchronisiert läuft und keine dead-locks erzeugt.
    Allerdings, darauf habe ich auch schon das ein oder andere mal hingewiesen, niemals ein CWnd oder davon abgeleitetes Objekt direkt an einen Thread übergeben und dort verwenden!
    Warum? Ich wiederhole:
    CWnd sind nicht thread-save! Darauf wird im MSDN immer wieder hingewiesen! Statdessen den HWND des Windows and den Thread übergeben, und mit CWnd::FromHandle( hWnd ) das CWnd objekt holen. Dann lässt sich damit prima arbeiten.

    Gruss, Gio



  • zhoosch schrieb:

    wech: weil kein MFC

    besser ist das.
    wär mir auch peinlich gewesen 😃



  • ten schrieb:

    hustbaer schrieb:

    Threads sind Die Hölle (tm).
    Das fieseste daran ist IMHO dass man erst merkt dass man nicht viel über Multithreading weiss, wenn man bereits viel mehr als der Durchschnittsprogrammierer über Multithreading weiss 🙂
    Oder anders gesagt: dass Leute die sich mit Multithreading nicht so auskennen oftmals glauben sie wüssten was sie tun. Was dann meistens ein Irrglaube ist.

    jetzt übertreibst du aber....

    Nö, tu' ich glaube ich nicht. 🙂



  • ok ich hab verstanden, ich muss das CWnd Objekt immer über das HWND holen.

    was ist denn besser? wenn ich dann mit dem CWnd Objekt arbeite und Controls verarbeite, oder über PostMessage??

    Was ist der Unterschied zwischen PostMessage und SendMessage?



  • Also mich machen Threads auch fix und alle :)... aber man will ja auch was lernen und ohne fleiß kein Preis. So jetzt aber zu diesem Thema, welches ich mit großen Interesse gerade gelesen habe :)... Beim Lesen sind mir dann 1000 von Fragen in den Kopf gekommen, aber vorallem eins verstehe ich nicht.

    Allerdings, darauf habe ich auch schon das ein oder andere mal hingewiesen, niemals ein CWnd oder davon abgeleitetes Objekt direkt an einen Thread übergeben und dort verwenden!
    Warum? Ich wiederhole:
    CWnd sind nicht thread-save! Darauf wird im MSDN immer wieder hingewiesen! Statdessen den HWND des Windows and den Thread übergeben, und mit CWnd::FromHandle( hWnd ) das CWnd objekt holen. Dann lässt sich damit prima arbeiten.

    Also wenn CWnd nicht thread-save ist, bedeutet das doch - wenn ich threadsafe richtig verstanden habe - das ein Objekt eines CWnd niemals von mehreren Threads "verwendet" werden darf bzw. drauf zugegriffen werden darf, weil es sonst zu undefinierten Zuständen kommen kann.

    Wieso ist es über den Handle eine Lösung? Ich hol mir doch über den Handle nur einen Zeiger auf das Objekt und wenn ich dann bei diesem Objekt wieder etwas aufrufe laufe ich doch wieder Gefahr oder?!

    Danke


  • Mod

    Was hälst Du im Algemeinen davon mal die Doku zu lasen, ehe Du solche FRAgen stellst.

    SendMessage liefert eine Nachricht direkt aus (funktioniert wie ein Aufruf der Fensterprozedur), PostMessage stellt die Nachricht in die Nachrichtenschleife und returniert sofort.

    SendMessage kann über Thread-Grenzen zum Deadlock führen, denn in diesem Fal muss auf dem Thread eine Nachrichtenschleife laufen um die Nachricht abzuholhen. Merke: Fenster sind threadafin!

    Netter Fehler aller Anfänger: PostMessage mit WM_SETTEXT zu verwenden. Bei PostMessage kann man keine Zeiger übergeben, weil man nicht weiß wielange eben der Bereich auf den der Zeiger verweist gültig gehalten werden muss...



  • @mayer123: ich denke mal wenn du mit mehre thread gleichzeitig das cwnd objekt verwendest, musst du denk ich mal das übe Critical SEction etc. machen, damit die thread nicht gleichzeitg das cwnd objekt verändern... so ist der zustand immer eindeutig.... (nehm ich mal an als anfänger was threads angeht)



  • @BorisDieKlinge: Da Cwnd ja nicht threadsaft ist bedeutet dies - nach meinem Verständnis - das ich zwar CriticalSection verwenden kann (in meinem Code) aber damit nicht sichergestellt ist, dass irgendwo intern Murks passiert (z.B. bekommt das Cwnd-Objekt eine Nachricht während "mein" Thread gerade eine Methode dort aufruft. Da das Cwnd nicht threadsafe ist ist nicht sichergestellt was nun passiert...

    Aber vielleicht könnte einer der Experten uns mal aufklären oder versteht uns keiner :)... oder ist das Niveau dieser Unterhaltung zu tief 😃



  • Hi ich bin zwar kein Experte... aber die Antwort steht in der MSDN:

    Windows-Handlezuordnungen
    Grundsätzlich kann ein Thread nur auf die von ihm erstellten MFC-Objekte zugreifen. Der Grund hierfür ist, dass temporäre und permanente Windows-Handlezuordnungen im lokalen Threadspeicher verwaltet werden. Auf diese Weise soll der gleichzeitige Zugriff von mehreren Threads aus verhindert werden. Ein Arbeitsthread kann z. B. keine Berechnung durchführen und anschließend die UpdateAllViews-Memberfunktion eines Dokuments aufrufen, um die Fenster zu ändern, die Ansichten der neuen Daten enthalten. Dies hat keinerlei Auswirkung, da sich die Zuordnung von CWnd-Objekten zu HWNDs lediglich auf den primären Thread bezieht. Dies bedeutet, dass ein bestimmter Thread möglicherweise eine Zuordnung eines Windows-Handles zu einem C++-Objekt aufweist, ein anderer Thread dasselbe Handle jedoch unter Umständen einem anderen C++-Objekt zuordnet. Änderungen, die in einem Thread vorgenommen wurden, werden in einem anderen Thread nicht widergespiegelt.

    Es gibt verschiedene Methoden zur Umgehung dieses Problems: Die erste Methode ist die Übergabe eines individuellen Handles (z. B. HWND) an den Arbeitsthread, anstelle von C++-Objekten. Der Arbeitsthread fügt anschließend diese Objekte seiner temporären Zuordnung hinzu, indem er die entsprechende FromHandle-Memberfunktion aufruft. Sie haben auch die Möglichkeit, das Objekt der permanenten Zuordnung des Threads durch Aufruf von Attach hinzuzufügen; dies sollten Sie jedoch nur tun, wenn Sie mit absoluter Sicherheit wissen, dass das Objekt länger als der Thread vorhanden sein wird.

    Sie können auch neue benutzerdefinierte Meldungen erstellen, die den unterschiedlichen Aufgaben entsprechen, die von den Arbeitsthreads durchgeführt werden, und diese Meldungen mit ::PostMessage im Hauptfenster der Anwendung bereitstellen. Diese Kommunikationsmethode ist mit dem Informationsaustausch zwischen zwei Anwendungen vergleichbar; der Unterschied besteht darin, dass beide Threads im selben Adressbereich ausgeführt werden.

    Gruß



  • Jochen trifft den Nagel! Ich bin mit meinem "nicht Thread-Safe" vielleicht etwas daneben, was das Verständnis betrifft, aber genau das habe ich eben nach langer Forschung selbst im MSDN so gefunden und peinlicherweise einfach so weitergegeben.

    Also: CWnd (und Derivate) können u.U. temporärer Natur sein. Übergibt man nun einem Thread ein CWnd aus irgendeiner Funktion, dann kann nach Verlassen eben jener Funktion dieses übergeben CWnd ungültig sein. Deswegen HWND (mit CWnd::GetSafeHwnd ()), da der zurückgelieferte Handle auch "out of scope" gültig ist (wenn nicht NULL ;)).

    Gruss, Gio


Anmelden zum Antworten