Thread zum aktualisieren
-
Hallo,
und zwar will ich in meinem Programm ( VC++ 2008 MFC Projekt ) ein Label aktualisieren mit der aktuellen Uhrzeit. Mit einem Timer will ich es nicht machen, da das Programm dann ziemlich "langsam" wird. Wenn ich nun ein Thread starte ( Habe schon ziemlich viele Möglichkeiten versucht, dann bringt mir der Compiler immer ein Fehler in der wincore.cpp wenn ich UpdateData durchführe oder auf ein Steuerelement zugreife).
Könntet ihr mir vllt. ein Beispiel Code geben für einen Thread, der z.B. immer in bestimmten Abständen ein UpdateData(FALSE) durchführt ? Oder kann man das mit einem Thread überhaupt realisieren ?
Danke
-
Also erstmal: Für ne Uhr ist ein eigener Thread ziemlich übertrieben. Da wird mit nem Timer nix langsam.
Zu deinem Problem: man kann aus einem Thread nicht auf GUI-Elemente eines anderen Threads (dein GUI-Thread) zugreifen.
Ich würde mir ein paar User-Defined-Messages erstellen und diese dann aus dem Thread an den GUI-Thread senden. Der kann dann drauf reagieren und die Uhrzeit aktualisieren.
-
Und wie kann ich dem GUI Thread etwas schicken oder wie weiss ich wie der heisst ? Könntest du mir da ein Beispiel geben ?
-
Na is doch eigentlich ganz einfach (suche bei google hätte auch geholfen). Erstell eine User Define-Message (#define WM_User_Message WM_APP+31), Gib deinem Thread das Handle deines GUI Threads mit, erstelle im GUI Thread in der MessageMap einen EIntrag ON_MESSAGE(WM_User_Message , StelldieUhr ) und die entsprechende Funktion StelldieUhr(), jetzt brauchste nur noch SendMessage in deinem WorkThread aufrufen und fertig.
Aber im Netz findest du genug Beschreibungen dazu
Aber wie schon gesagt, für ne Uhr is das viel zu viel Aufwand, da reicht der timer alle mal aus, oder willst du Millisekunden Anzeigen?
Gruß Matthias
-
Warum sollte man aus einen Thread kein Steuerelement aktualisieren können.
Ist sogar möglich mit 70 Threads ein Gridcontrol upzudaten.
Man darf nur nicht UpdateData aufrufen.
Der Rest steht in der FAQ.
-
Unix-Tom schrieb:
Warum sollte man aus einen Thread kein Steuerelement aktualisieren können.
Weil ein RedrawWindow/UpdateData aufruf zum Beispiel zu einem Deadlock führen könnte...

-
Habe doch geschrieben das UpdateData nicht geht.
Zu deinem Problem: man kann aus einem Thread nicht auf GUI-Elemente eines anderen Threads (dein GUI-Thread) zugreifen.
Habe mich darauf bezogen und diese Aussage ist falsch.
-
In diesem Fall macht ein Thread einfach keinen Sinn.
Das neu Zeichnen darf nur der GUI-Thread, also kann man IMO auch gleich einen stinknormalen SetTimer() Timer verwenden.Ob ich mir von Timer WM_TIMER generieren lasse, oder vom Timer-Thread per PostMessage irgendwas poste ist (fast) egal.
-
@hustbaer: ACK!
-
In diesem Fall macht es keine Sinn das ist richtig.
Es gibt aber durchaus sehr viele Fälle wo es machbar ist.
IN meinem Fall ein Linemonitor wo im Grid 70 Zeilen sind. Jeder Thread hat seine Zeile und ändert die.
Also ist es möglich von Threads aus. Ich habe auch nicht über den Sinn geschrieben sondern nur das es möglich ist.
Deshlab gibt es die Unterscheidung zw. Workerthreads und GUITHREADS.
-
Avoiding UpdateData:
http://www.flounder.com/updatedata.htmWorker threads and the GUI II: Don't touch the GUI (gilt auch für UI threads):
http://www.flounder.com/workerthreads.htm
-
Joseph Newcomers Meinung über UpdateData teile ich nicht ganz.
70% der aufgeführten Probleme wären zu umgehen indem man den Rückgabewert von DoModal auf IDOK prüft.
Ansonsten stimme ich mit ihm darin überein, dass es keinen Sinn mach 100 Controls abzufragen um den Inhalt eines einzigen zu bekommen, dass der Nutzer verändert hat

-
@Unix-Tom:
Das war hauptsächlich an den OP gerichtet, und nicht an dich.
Auch wenn ich nicht verstehe, wieso du soetwas hier empfiehlst.IN meinem Fall ein Linemonitor wo im Grid 70 Zeilen sind. Jeder Thread hat seine Zeile und ändert die.
Prost!
-
Ich habe es nicht empfohlen.
Es war damals in meiner Situation das beste.
70 Threads waren es deshalb weil es 70 Leitungen gab und jeder Thread war für eine zuständig.
Klar hätte ich es auch anderes lösen können . Zum Glück gibt es ja in C++ nicht nur eine Lösung.
Ich wollte lediglich nicht die Aussage stehen lassen das man von einem Thread nicht ein Control der GUI ändern kann. Es geht auch wenn es in vielen Fällen nicht notwedig ist und in manchen Fällen nicht anders geht.
-
Ich wollte lediglich nicht die Aussage stehen lassen das man von einem Thread nicht ein Control der GUI ändern kann.
Kann man aber normalerweise nicht. Bzw. kann man schon oft, sollte man aber grundsätzlich nicht.
Klar hängt ob man es kann oder nicht davon ab, welches Framework/OS/... man verwendet.MFC Controls sind aber grundsätzlich nicht thread-safe. Wenn du das Control aus irgendeinem Thread aktualisierst, kanns dir halt beim Zeichnen schön um die Ohren fliegen. Oder wie willst du verhindern dass das Control gezeichnet wird, während der Worker-Thread darauf zugreift?
-
Unix-Tom schrieb:
Ich wollte lediglich nicht die Aussage stehen lassen das man von einem Thread nicht ein Control der GUI ändern kann. Es geht auch wenn es in vielen Fällen nicht notwedig ist und in manchen Fällen nicht anders geht.
Es geht viel auch wenn es nicht unbedingt schlau/sicher ist.
Sicher ist imho nur PostMessage an den Besitzer der control.
-
Wenn man mit Threads arbeitet muss mann sowieso Sync einbauen.
Ich sagte nicht das es schlau ist einfach ein Control zu ändern ohne darauf zu schauien das dies kein anderer zur gleichen Zeit macht.
-
Unix-Tom schrieb:
Wenn man mit Threads arbeitet muss mann sowieso Sync einbauen.
Ich sagte nicht das es schlau ist einfach ein Control zu ändern ohne darauf zu schauien das dies kein anderer zur gleichen Zeit macht.flounder schrieb:
The Best Synchronization Is No Synchronization: Alternatives to semaphores, mutexes, and CRITICAL_SECTIONs
-
@Unix-Tom: Ich wiederhole meine Frage: wie willst du verhindern dass das Control gezeichnet wird, während der Worker-Thread darauf zugreift?
-
EOP schrieb:
Der erste Absatz (nach der Einleitung) in dem Artikel ist gefährlicher Bullshit. Der Author schein zwar nicht gerade eine Vollvase zu sein, aber dennoch schreibt er da (zumindest) im Absatz "When it isn't needed at all" totalen Topfen.
Auf x86 CPUs mag das so funktionieren, aber als allgemein gültige Aussage ist es einfach nur falsch.
p.S.: das warum ist leider etwas schwer zu erklären. Im Prinzip geht es um die Sichtbarkeit von Änderungen, bzw. allgemeiner: darum was einem ein bestimmtes Speichermodell garantiert, und nicht garantiert. Und ganz allgemein kann man einfach nicht davon ausgehen, dass das Schreiben einer volatile Variable "release" Semantik hätte, bzw. das Lesen einer volatile Variable "acquire" Semantik.