Threads und UpdateData
-
Hallo,
folgendes Problem:
Ich erzeuge ein von CPropertyPage abgeleitetes Fenster und übergebe den HWND an einen Thread. Dieser soll bei einem Event UpdateData aufrufen. Ich hole mir also im Thread den Zeiger auf das CWnd mit CWnd::FromHandle und rufe UpdateData auf. Nur leider wird dann nur die Basisversion von DoDataExchange aufgerufen und nicht die virtuelle der CPropertyPage-Klasse.
Ich hab jetzt schon wie wild hin und her gecastet aber brachte leider alles nichts. Irgendwie scheint die Objektstruktur über die Threadgrenze hinaus zerstört zu werden
Dankbar für jede Hilfe,
connan.

-
Las es einfach bleiben. Sende eine Nachricht an das Fenster, dass in dem entsprechenden ursprünglichen Thread, in dem der Dialog erzeugt wurde UpdateData aufgerufen wird. Alles andere ist einfach übel.
Man sollte MFC Objekte Zeiger und auch Fenster Handle nach Möglichkeit nicht über Threadgrenzen hinweg weitergeben.
-
Danke, mit Nachrichten funktionierts. Ich dachte immer Handles wären Threadsicher!? Wie kann ich denn sonst noch eine Nachricht senden?
Wo ich mir auch nicht ganz sicher bin ist, ob ich nach CWnd::FromHandle auch CWnd::DeleteTempMap aufrufen muss, ist das Handle über die Threadgrenze noch 'attached' oder nicht?
Achso, und gibts evtl. eine Nachricht die direkt UpdateData auslöst?.
-
connan schrieb:
Ich dachte immer Handles wären Threadsicher!? Wie kann ich denn sonst noch eine Nachricht senden?
Handles sind Threadsicher. Nur wird in dem Moment in dem Du eine Nachricht per SendMessage an einen anderen Thread sendest Dein Thread angehalten, bis die Nachricht vom anderen Thread bearbeitet wurde. Das ist dann eine Threadsynchronisation die es zu vermeiden gilt, und die auch leicht Deadlocks verursachen kann.
connan schrieb:
Wo ich mir auch nicht ganz sicher bin ist, ob ich nach CWnd::FromHandle auch CWnd::DeleteTempMap aufrufen muss, ist das Handle über die Threadgrenze noch 'attached' oder nicht?
Achso, und gibts evtl. eine Nachricht die direkt UpdateData auslöst?.Die Maps sind Threadlokal und Du musst nichts tun mit einem Handle das durch FromHandle ermittel wurde. Das Problem siehst Du hier schon: DeleteTempMap wird nur dann aufgerufen wenn Du einen GUI Thread hast. Andernfalls nicht.
Also warum überhaupt CWnd Objekte verwenden?
Mach es nicht und Du hast keine Schwirigkeiten.Es gibt keine Nachricht für UpdateData. Wenn musst Du selber eine definieren.
-
Ich nehme für die Nachrichten PostMessage die sollte doch sofort wieder returnieren.
Mit den CWnd-Objekten hast Du natürlich recht, ich dachte halt nur wegen UpdateData...;)
Kann mann evtl. für Threads eine Art Shared-Memory vereinbaren, so daß es doch funktioniert? Nach meinem Verständniss (;)) sollte doch das Codesegment threadsafe sein!?
-
connan schrieb:
Ich nehme für die Nachrichten PostMessage die sollte doch sofort wieder returnieren.
Mit den CWnd-Objekten hast Du natürlich recht, ich dachte halt nur wegen UpdateData...;)
Kann mann evtl. für Threads eine Art Shared-Memory vereinbaren, so daß es doch funktioniert? Nach meinem Verständniss (;)) sollte doch das Codesegment threadsafe sein!?Sicher returniert PostMessage sofort. Aber damit erreicht man oft nicht was man will. Das sofortige aktualisieren des Dialoges. Zudem kann man mit PostMessage keine Zeiger übergeben oder ähnliches. Eben nur eine Nachricht absetzen. Aber das langt ja auch oft.
UpdateData aus einem anderen Thread ausführen ist von übel... darüber braucht man gar nicht weiter zu diskutieren, und performant ist es sowieso nicht.
Man muss keinen Shared Memory nehmen. Jeder Speicher tut es. Man muss nur den Zugriff synchronisieren (CriticalSection). Und das bremst den Thread in vielen Fällen schon wieder aus. Und schon gar nicht sollte man eine CriticalSection locken und dann mal eben SendMessage machen etc.
Am besten funktionieren mehrere Threads wenn es zwischen den Threads so wenig Berührungspunkte wir möglich gibt. Und ein GUI/Windows Handle gehört in die Kategorie "viel Berührung" / "viel Abhängigkeit".