SendMessage PostMessage Struktur
-
Prof. Dr. Dr. Gates schrieb:
Übergibt man PostMessage Zeiger auf lokale Variablen, dann sind diese schon ungültig, wenn der Empfänger die Nachricht bekommt.
ich spreche auch nicht von lokalen variabeln.... "heap"
Boris hat recht wenn er mit Prozessen zwei unterschiedliche Thread in ner anwendung meint....
Wenn du Prozess als "zwei unterschiedliche Threads in ner anwendung" definierst, dann wundert es mich nicht, daß du keinen Plan hast.
Man muss mich nicht mögen, aber hier jetzt auf Biegen und Brechen zu versuchen, die FALSCHINFORMATION von Boris zu verteidigen, ist hochgradig lächerlich. Aber vermutlich steckt hinter "Prof. Dr. Dr. Gates" auch niemand geringeres als er selbst
-
Die definition von Prozess war von ihm falsch gewählt...
Aber wenn du dich hier so aufplustert, und meinst du bist der übelste super Informatik Student.( Der Nick ist eh lächerlich sehr viele hier sind Diplom. Informatiker) .und die haben keine so große Klappe:)
Und wenn du denkst man kann nur Werte versenden und keine Pointer welche auf Daten zeigen dann solltest du noch paar Semester drauf legen.
-
Laber keinen Müll. Ich hab dich doch vorher noch gewarnt, aber du wolltest dich ja unbedingt aufplustern. jetzt musstest du es eben auf die harte tour lernen, aber jetzt kannste auch wieder aufhören zu heulen.
-
Elektronix schrieb:
@Wurst
Das war auch nicht auf Dich gemünzt. Es gibt genügend Profis hier, die sagen: Man kann per SendMessage Zeiger versenden- und die werden wohl wissen, was sie erzählen.Das geht mit WM_COPYDATA, wo man dann einen zeiger+länge angibt, und dann die daten byte für byte in den prozess des zielfensters kopiert werden, und der pointer dann im zielprozess ganz ander aussehen kann.
Aber bezogen auf den Fragesteller: Wer mit SendMessage noch nicht umgehen kann, wird wohl kaum mit Prozessen um sich schmeißen.
Der OP meint mit anderes Fenster wohl einen anderen Prozess, da er von HGLOBAL geredet hat, und das zu 16-Bit Zeiten für Prozessübergreifenden speicher verwendet wurde.
Es kann ja sein, daß ich was falsch verstehe: Benötigt jedes Fenster, auch jedes Child-Fenster- einen eigenen Prozess?
Nö, das währe reine resourcenverschwendung.
...
Hier passiert alles in einem einzigen Prozess also ohne IPC/WM_COPYDATA
Ich hoffe ich konnte die Sache etwas aufklären,
Gruß wurst
-
Oha, was ein Post
.
Also mich stört das aggressive posten von "Dipl.Inf.Student" auch etwas und nur weils im Namen steht, kann da ja trotzdem ein (kleines) Script-Kiddie hinter sitzen, ABER: er hat sozusagen Recht
(hab den Thread nur überfolgen). Der Threadersteller hat weder was von Threads noch was von Prozesses gesagt und genau das ist das Problem: Mit "eine Nachricht an ein Fenster senden" kann sowohl ein Fenster des eigenen Threads, als auch ein Fenster eines anderen Prozesses gemeint sein (
fehlende Hintergrundinformation). Daher war die Frage von "Dipl.Inf.Student" schon sinnvoll - wäre auch meine Gegenfrage gewesen. Das vllt. erstmal zur Konfliktauflösung^^.
Zum Problem (keine Ahnung, ob das jetzt so klar wurde): Threads gehören immer zu einem Prozess. Innerhalb eines Prozesses (und damit auch innerhalb von Threads mit dem gleichen Prozess) gilt der Adressraum für das jeweilige Programm, dabei kann aber nicht auf den Adressraum eines anderen Programmes/Prozesses zugegriffen werden, da Windows das verbietet (sicherer). Stürzt nämlich ein Programm wären fehlerhafter Zeigerarithmetik ab, sorgt das nicht für den Absturz aller Programm oder sogar des gesamten OS. Man kann mit SendMessage/PostMessage also prozess-intern Daten "verschicken". An Fenster anderer Programm geht das aber nicht.
Dabei sollte der Unterschied zwischen SendMessage und PostMessage vllt. noch klar werden: SendMessage sorgt, falls die Nachricht an ein Fenster aus einem anderen Thread geschickt wird, für ein Context-Swichting. Das heißt, dass der Thread aufgrund des Aufrufs gewechselt wird und die Funktion erst dann zurückkehrt, wenn die jeweilige Fensterprozedur "geantwortet" hat. Das ist wichtig bei der Synchronisation von Threads und wichtig bei der Übermittlung von Zeigern: Es muss nämlich sichergestellt werden, dass der Zeiger in der Fensterprozedur noch gültig ist, dazu folgendes Beispiel:// ... UINT uiLen = ...; SendMessage(hWnd, WM_USER + 1, 0, reinterpret_cast<LPARAM>(new TCHAR[uiLen])); // ... /* In der entsprechenden Ziel-WndProc: */ case WM_USER + 1: { TCHAR* pszBuf = reinterpret_cast<TCHAR*>(lParam); assert(pszBuf); // Irgendwas mit pszBuf machen [...]. delete [] pszBuf; } break; // bzw. return
Ob man nun SendMessage oder PostMessage im obrigen Beispiel verwendet, ist egal. (Wenn das SendMessage in einem Thread aufgerufen wird, sollte man auf jeden Fall PostMessage verwenden!)
Bei folgendem Beispiel hingegen, *muss* man SendMessage verwenden:TCHAR szBuf[1024]; SendMessage(hWnd, WM_USER + 1, 0, reinterpret_cast<LPARAM>(szBuf)); // ... /* In der entsprechenden Ziel-WndProc: */ case WM_USER + 1: { TCHAR* pszBuf = reinterpret_cast<TCHAR*>(lParam); assert(pszBuf); // Irgendwas mit pszBuf machen [...]. } break; // bzw. return
Hoffe, damit ist es allen klar
.
-
@Wurst und Codefinder
Danke für die Aufklärung und @Codefinder für das diplomatische Einmischen.
@Wurst
Ich habe den Eingangspost so verstanden, daß er Zeiger zwischen Fenstern eines einzelnen Prozesses versenden will und nur aus Ratlosigkeit
Alles versucht bis hin zu HGLOBAL und Co.
Kann natürlich sein, daß ich das mißverstehe. Aber ich denke, wenn jemand mit mehrfach-Prozessen umgeht, ist er auch klug genug, seine Frage entsprechend zu formulieren bzw. SendMessage und PostMessage richtig einzusetzen. CodeFinder hat fehlende Hintergrundinfos erwähnt, das sollte beim Umgang mit Prozessen eigentlich nicht passieren. Daher denke ich eher, es bleibt bei einem Childfenster im selben Prozess.
Wäre vom OP halt schön, wenn er das selbst aufklären könnte.Wie auch immer, hoffentlich kommt jetzt ein bißchen Ruhe in die Diskussion.
-
Hätte ja nicht so ausarten müssen, wenn man von Anfang an mein Fachwissen als solches akzeptiert hätte.
So aber jetzt ist auch hier Ruhe, da stimme ich zu.
-
sorry wenn dir der begriff Prozess nich gefallen hat. meinte damit trhead bzw. prozess innerhalb eines prozesse also trheads!
Dein Fachwissen hin oder her! jeder hat recht , je nachdem wie man die frage interpretiert..
-
Nö, du hattest Unrecht und versuchst nun dich mit wirrem und sinnfreiem Umdefinieren etablierter Begriffe aus der Schlinge zu ziehen. Aber ist ja jetzt auch egal.
-
Dipl. inf. Studnet schrieb:
Nö, du hattest Unrecht und versuchst nun dich mit wirrem und sinnfreiem Umdefinieren etablierter Begriffe aus der Schlinge zu ziehen. Aber ist ja jetzt auch egal.
dito
-
Schlussendlich kann man Dipl.Inf.Student doch nur als Troll einstufen. Er hat nichts zur Lösung des Problems beigetragen, weder abstrakt, noch konkret. Außerdem hat er das Thema des Threads in die völlig falsche Richtung gebracht (in Regelfall versendet man Messages zwischen Threads und nicht zwischen Prozessen). Dazu dann noch die arrogante und beleidigende Art und Weise, die er hier an den Tag gelegt hat...
Prima Einführung hier Student, ich hoffe, wir sehen Dich nicht wieder. Leute wie Dich braucht keiner.BTT:
@CodeFinder: Funktioniert Dein Beispiel ohne Einschränkungen, mit jedem Compiler? Manchmal habe ich das Gefühl, der BCB nimmt es einem übel, wenn man Speicher nicht im gleichen Thread wieder freigibt, in dem man ihn reserviert hat.
Ich hatte ein Projekt, in dem ich das ähnlich gemacht habe, wie in Deinem Beispiel, aber nach ein paar Wochen Laufzeit ist mir das Programm immer weggeschmiert, da kein Speicher mehr reserviert werden konnte... Erst als ich das so umgeschrieben habe, dass der Speicher immer in dem Thread freigegeben wird, in dem er auch reserviert wurde, ist der Fehler verschwunden (da dies aber weitere Umstrukturierungen im Programm notwendig machte, kann ich das nur vermuten).
-
Joe_M schrieb:
Erst als ich das so umgeschrieben habe, dass der Speicher immer in dem Thread freigegeben wird, in dem er auch reserviert wurde, ist der Fehler verschwunden
Das ist auch vorrausetzung für die tadelose funktionweise... Thread A: resrviert speicher und Thread B bzw. GUI bekommt einen Pointer auf den speicher via PostMessage. Thread B sollte die daten auch NUR lesen..Thread A sollte sich um die zerstörung kümmern... Problematisch wird es auch wenn Thread A bspw. die Daten in einem best. intervall aktualisiert, und du die Daten in jedem zyklus an Thread B schickst. Dadurch das PostMessage asyncron arbeitet, könnte es sein das Thread B die daten liest und Thread A gleichzeitig die Daten überschreibt. Syncronisation ist angesagt..
-
BorisDieKlinge schrieb:
Das ist auch vorrausetzung für die tadelose funktionweise... Thread A: resrviert speicher und Thread B bzw. GUI bekommt einen Pointer auf den speicher via PostMessage. Thread B sollte die daten auch NUR lesen..Thread A sollte sich um die zerstörung kümmern... Problematisch wird es auch wenn Thread A bspw. die Daten in einem best. intervall aktualisiert, und du die Daten in jedem zyklus an Thread B schickst. Dadurch das PostMessage asyncron arbeitet, könnte es sein das Thread B die daten liest und Thread A gleichzeitig die Daten überschreibt. Syncronisation ist angesagt..
Warum sollte das so sein! Wenn man ein vernünftiges Speicherhandlunghat (z.B. mit Smart-Ptrn), dann ist es mir egal wer den Speicher freigibt.
Gerade wen ich auch noch mehrere Workerthreads habe ist die Freigabe der Daten im Worker Unsinn.
"Der gibt die Daten frei, der sie als letzter benutzt" ist meines Erachtens die weitaus bessere Regel.
Und wie gesagt, es gibt seit TR1 so schöne intelligente Zeiger...Meistens vermeide ich es wie die Pest Daten mit Post/SendMessage zu senden. Ich arbeite lieber mit einer Queue, die die Daten erhält vom Worker und eben aus der der UI Thread liest. Und selbst hier vermeide ich gerne Nachrichten sondern arbeite lieber mit Events...
-
ja hast recht, mit smartpointer geht das ^^
-
Wie geht das denn mit der queue?
hat der Thread ein queue container, beschreibt diesen, und schickt ne referenz per postmessage an die GUI?
-
Nimm einfach eine std::queue, pack einen Synchronisationsmechanismus drum (zB mit CriticalSection) und sende dem Empfänger einfach nur die Botschaft, dass er was abholen soll. An Stelle der Nachricht kann man auch Events verwenden (die ich ebenfalls sehr zu schätzen gelernt habe).
Ich hab damals, in meiner Verzweiflung einen Ringpuffer gebastelt...
Ich muss mal schauen, wo das Problem genau herkommt. Ob es etwas Compilerspezifisches ist, oder an der Speicherverwaltung der VCL-Klassen im Borland C++ Builder liegt... Werde ich aber in den nächsten Tagen nicht zu kommen.
-
ok danke,
aber wie gehts das mit den events? ich muss ja dann in der GUI nen thread laufen haben, welcher auf ein events wartet, welches ich vom anderen thread aus setze oder?
-
Wie man es mit Events macht hängt davon ab, wie Dein UI Thread funktioniert.
Ich verwende gerne MsgWaitForMultipleObjectsEx...
Aber man kann auch einfach mit WaitForSingleObject(,0) prüfen ob ein Event gesetzt ist,
Wo Du das machst, ob in einem Timer, oder in einem anderen Handler ist sehr abhängig von Deiner Applikation.Es gibt eben kein pauschales: "Man macht es so und so..."
Nur deshalb habe ich mich überhaupt in diese Diskussion eingemischt. Mit war die Antwort von BorisDieKlinge zu pauschal. Ich wollte nur andere Möglichkeiten auch noch genannt haben.
-
Das ist irgendwo warten muss auf ein Event is mir klar.. aber dafür brauch ich ja ein extra thread in der UI welcher auf das event warte und dann gegenfalls die queue lese.. mit nem post message kann ich mir den extra thread der auf ein evetn warte sparen.. das meinte ich
-
BorisDieKlinge schrieb:
sorry wenn dir der begriff Prozess nich gefallen hat. meinte damit trhead bzw. prozess innerhalb eines prozesse also trheads!
Dein Fachwissen hin oder her! jeder hat recht , je nachdem wie man die frage interpretiert..
Sorry, aber das ist Unfug. "jeder hat recht , je nachdem wie man die frage interpretiert.." - was ist das eigentlich für eine sinnfreie Aussage?
Joe_M. schrieb:
BTT:
@CodeFinder: Funktioniert Dein Beispiel ohne Einschränkungen, mit jedem Compiler? Manchmal habe ich das Gefühl, der BCB nimmt es einem übel, wenn man Speicher nicht im gleichen Thread wieder freigibt, in dem man ihn reserviert hat.
Ich hatte ein Projekt, in dem ich das ähnlich gemacht habe, wie in Deinem Beispiel, aber nach ein paar Wochen Laufzeit ist mir das Programm immer weggeschmiert, da kein Speicher mehr reserviert werden konnte... Erst als ich das so umgeschrieben habe, dass der Speicher immer in dem Thread freigegeben wird, in dem er auch reserviert wurde, ist der Fehler verschwunden (da dies aber weitere Umstrukturierungen im Programm notwendig machte, kann ich das nur vermuten).Also: ja^^. Eigentlich gilt der gleiche Adressraum innerhalb eines Prozesses. Hab vllt. irgendwo noch ne BCB-Installer-Datei - könnte das dann mal ausprobieren, aber wenn das Problem eben nur "manchmal" auftritt und dann auch nur "eventuell" aus dem Grund, ist das schwierig nachzuvollziehen
. Aber kann (wie Du schon angedeutet hast) vllt. an ein paar "Eigenheiten" VCL-Klassen bzw. des Compiler sein^^.
BorisDieKlinge schrieb:
Das ist auch vorrausetzung für die tadelose funktionweise... Thread A: resrviert speicher und Thread B bzw. GUI bekommt einen Pointer auf den speicher via PostMessage. Thread B sollte die daten auch NUR lesen..Thread A sollte sich um die zerstörung kümmern..
Nein, das ist *nicht* "vorrausetzung für die tadelose funktionweise"...