SendMessage PostMessage Struktur



  • Prozessübergreifend



  • WestWorld schrieb:

    Hallo,

    Ich möchte gerne via SendMessage bzw. PostMessage eine Nachricht an ein anderes Fenster schicken. Die Nachricht soll über meinetwegen WM_MYMESSAGE (benutzdefiniert) heißen. Funktioniert ja auch alles bis hierher. Aber wenn ich eine Zeichenkette oder gar eine Struktur (struct XYZ { char str1[256]; char str2[256]; }; )über diese Funktionen schicke kriege ich im anderen Fenster nur Schrott. ALles versucht bis hin zu HGLOBAL und Co. Vielleicht weiß jemand weiter. Danke. 😕

    Zeiger auf Strings oder Strukturen sollte man nie mit PostMessage schicken (es sei denn, man weiß genau, was man tut). Im Gegensatz zu SendMessage kehrt PostMessage sofort zum Aufrufer zurück und der Code wird weiter abgearbeitet. Übergibt man PostMessage Zeiger auf lokale Variablen, dann sind diese schon ungültig, wenn der Empfänger die Nachricht bekommt.



  • Langsam plädiere ich doch dafür, unregistrierte arrogante Dipl.Inf.Studenten auszuschließen. 😡 Typen wie ihm verdanken wir solche Diskussionen:
    ➡ http://www.c-plusplus.net/forum/viewtopic-var-t-is-212868.html



  • Jetzt pack aber mal wieder die unreg Keule ein.

    Boris hat in seinem Codebeispiel behauptet, dass man einfach mittels Pointer Daten zwischen 2 Prozessen austauschen kann:

    Boris schrieb:

    wieso? wenn die daten im prozess B aufm heap liegen kann prozess A über dnen zeiger auf diedaten zugriefen..

    Also kann man einfach einen Zahlenwert zwischen 2 prozessen verschicken, und dann auf die date zugreifen.
    Na wenn das die Meinung der Mehrheit ist, dann wundert mich nichts mehr ...



  • Ü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....



  • @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. Ich kann es nur nicht leiden, wenn ein dahergelaufener Unreg den Profis in der Community sagen will, daß sie zu blöd sind. Wenn er das nötig hat, soll er sich ein Forum suchen, wo das aktzeptiert wird. Hier ist es unerwünscht.

    Ich wundere mich, daß hier immer von "Prozessübergreifend" geredet wird, obwohl im Eingangspost davon keine Rede ist. Der Dipl.Inf.Student hat das gleich in seiner ersten Antwort erfunden, um allen anderen ihre Blödheit vorzuhalten. Aber bezogen auf den Fragesteller: Wer mit SendMessage noch nicht umgehen kann, wird wohl kaum mit Prozessen um sich schmeißen.

    Es kann ja sein, daß ich was falsch verstehe: Benötigt jedes Fenster, auch jedes Child-Fenster- einen eigenen Prozess? Oder kann ein einzelner Prozess nicht mit mehreren Fenstern umgehen?

    Ich bin zwar kein Profi-Progger. Aber: Dieses Prgramm versendet die Adresse einer Struct an ein Child-Fenster (Usernachricht WM_SENDDATA), und es funktioniert:

    #define STRICT
    #include <windows.h>
    #define ChildHight 140
    #define ChildWidth 300
    struct OutputData{
    
    						POINT ptCursor;                    //Position des Mauscursors
                      SIZE	size; 							  //Textgröße
                      char szLbtMsg[128];                //Ausgabe linke Maustaste
                      char szRbtMsg[128];                //Ausgabe rechte Maustaste
                      char szMmvMsg[128];                //Ausgabe Mausposition
                      bool ArrowKeys[4];
    
                      int x, y;
                      int i;  									// Zähler
                      };
    
    const UINT WM_GETDATA = WM_APP + 1;
    const UINT WM_SENDDATA = WM_APP + 2;
    LRESULT CALLBACK ChildProc (HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    const char szAppName[] = "Tastaturabfrage";
    const char szChildName[] = "ChildWindow";
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    							PSTR szCmdLine, int iCmdShow)
    {
    	MSG	msg;
       HWND	hWnd;
       WNDCLASS	wc;
    
       wc.cbClsExtra			=0;
       wc.cbWndExtra			=0;
       wc.hbrBackground		=(HBRUSH)GetStockObject(WHITE_BRUSH);
       wc.hCursor				=LoadCursor(NULL, IDC_ARROW);
       wc.hIcon             =LoadIcon(NULL, IDI_APPLICATION);
       wc.hInstance			=hInstance;
       wc.lpfnWndProc			=WndProc;
       wc.lpszClassName		=szAppName;
       wc.lpszMenuName		=NULL;
       wc.style					=CS_VREDRAW|CS_HREDRAW;
    
       RegisterClass(&wc);
    
       wc.hIcon = NULL;
       wc.lpfnWndProc		=ChildProc;
       wc.lpszClassName		=szChildName;
    
       RegisterClass(&wc);
    
       hWnd = CreateWindow(	szAppName,
       							szAppName,
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            NULL,
                            NULL,
                            hInstance,
                            NULL);
       ShowWindow(hWnd, iCmdShow);
       UpdateWindow(hWnd);
    
       while (GetMessage(&msg, NULL, 0, 0))
       {
       	TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
       return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
       static HWND hChild;
    
       static OutputData OutData;
       //OutData.i = 0;//Variante mit dem Wert der Variablen
       //struct OutputData *pOutData = &OutData;//Initialisieren des Zeigers
    
       //pOutData->i = 0; //einfache Schreibform mit Zeiger
       //(*pOutData).i = 0; //normale Schreibform mit Zeiger
       switch (message)
       {
       	case WM_CREATE:
          {
           	hChild = CreateWindow (szChildName,
             					NULL,
                            WS_CHILD|WS_VISIBLE|WS_DLGFRAME,
                            0,
                            0,
                            ChildWidth,
                            ChildHight,
                            hWnd,
                            NULL,
                            ((LPCREATESTRUCT)lParam)->hInstance,
                            NULL);
             return 0;
          }
          //////////////////////////////////////////////////////////////////////////
          case WM_GETDATA:
          {
          	bool Pm;
          	MessageBox(hWnd, "WM_GETDATA ist angekommen", "Fensternachricht", MB_OK);
          	Pm = PostMessage(hChild, WM_SENDDATA, 0, (LPARAM)&OutData);
    
             if (Pm == FALSE)
             {
             	MessageBox(hWnd, "WM_SENDDATA wurde nicht gesendet", "Fensternachricht", MB_OK);
             }
             return 0;
          }
    
        ////////////////////////////////////////////////////////////////////////////
        	case WM_SENDDATA:
          {
          	//MessageBox(hWnd, "WM_SENDDATA angekommen", "Fensternachricht", MB_OK);
             OutData.ptCursor.x=  OutData.ptCursor.x + LOWORD(lParam);
             OutData.ptCursor.y = OutData.ptCursor.y + HIWORD(lParam);
             MoveWindow(hChild,OutData.ptCursor.x,OutData.ptCursor.y, ChildWidth, ChildHight, TRUE);
          }
    
       	case WM_SIZE:
          {
          	RECT rect;
          	rect.left = 0;
             rect.right = 0;
          	rect.right = LOWORD(lParam);
             rect.bottom = HIWORD(lParam);
             return 0;
          }
    
          case WM_MOUSEMOVE:
          {
          	switch (wParam)
             {
             	case MK_RBUTTON:
                {
                	OutData.ptCursor.x = LOWORD(lParam); //ohne diese beiden Zeilen läuft die
             		OutData.ptCursor.y = HIWORD(lParam); //Schrift dem Cursor hinterher.
                 	OutData.x = OutData.ptCursor.x;
                 	OutData.y = OutData.ptCursor.y;
                   MoveWindow(hChild,OutData.ptCursor.x,OutData.ptCursor.y, ChildWidth, ChildHight, TRUE);
                }
             }
          	OutData.ptCursor.x = LOWORD(lParam);
             OutData.ptCursor.y = HIWORD(lParam);
             wsprintf(OutData.szMmvMsg, "Mauscursor an Pos.:x = %-04d, y = %-041d", OutData.ptCursor.x, OutData.ptCursor.y);
             InvalidateRect(hWnd, 0, TRUE);
             break;
          }
    
          case WM_LBUTTONDOWN:
          {
          	OutData.ptCursor.x = LOWORD(lParam);
             OutData.ptCursor.y = HIWORD(lParam);
    
             wsprintf(OutData.szLbtMsg, "Linke Maustaste an Pos.:x = %04d, y = %04d", OutData.ptCursor.x, OutData.ptCursor.y);
             InvalidateRect(hWnd, 0, TRUE);
             break;
          }
    
          case WM_RBUTTONDOWN:
          {
             wsprintf(OutData.szRbtMsg, "Rechte Maustaste an Pos.:x = %04d,y= %04d", OutData.ptCursor.x, OutData.ptCursor.y);
             InvalidateRect(hWnd, 0, TRUE);
             break;
          }
       	case WM_KEYDOWN:
          {
            	switch (wParam)
          	{
             	case VK_LEFT:
                	OutData.ArrowKeys[0] = true;
    					break;
    
                case VK_UP:
                	OutData.ArrowKeys[1] = true;
                   break;
    
                case VK_RIGHT:
                	OutData.ArrowKeys[2] = true;
                   break;
    
                case VK_DOWN:
                	OutData.ArrowKeys[3] = true;
                   break;
                default:
                	return 0;
             }
    
             //InvalidateRect (hWnd, NULL, FALSE);//Macht den Client-Bereich ungültig, dieser wird bei
    														  //der nächsten WM_PAINT neu gezeichnet.	         													
             return 0;
          }
    
          case WM_KEYUP:
          {
          	switch (wParam)
             {
             	case VK_LEFT:
               		OutData.ArrowKeys[0] = false;
    					break;
                case VK_UP:
                	OutData.ArrowKeys[1] = false;
                	break;
    
          	   case VK_RIGHT:
             	  	OutData.ArrowKeys[2] = false;
                   break;
    
          	   case VK_DOWN:
             	  	OutData.ArrowKeys[3] = false;
                   break;
                default:
                	return 0;
             }
    
             //InvalidateRect (hWnd, NULL, FALSE);
             return 0;
          }
          //!!  Ohne das ChildWindow käme die Ausgabe in diesem Abschnitt.  !!
          /*case WM_PAINT:
          {
          	PAINTSTRUCT ps;
             HDC			hDC;
    
             char szKeyStatus[40];
             int iKeyLength;
    
             hDC=BeginPaint(hWnd, &ps);
             for (OutData.i = 0; OutData.i<4; OutData.i++)
             {
             	iKeyLength = wsprintf(szKeyStatus, "Status Pfeiltaste %i: %i", OutData.i, OutData.ArrowKeys[OutData.i]);
    
                GetTextExtentPoint32(hDC, szKeyStatus, iKeyLength, &OutData.size);
    
                TextOut(hDC, OutData.x, OutData.y + OutData.i * OutData.size.cy, szKeyStatus, iKeyLength);
                TextOut(hDC, OutData.x, OutData.y + 5 * OutData.size.cy, OutData.szLbtMsg, lstrlen(OutData.szLbtMsg));
                TextOut(hDC, OutData.x, OutData.y + 6 * OutData.size.cy, OutData.szRbtMsg, lstrlen(OutData.szRbtMsg));
                TextOut(hDC, OutData.x, OutData.y + 7 * OutData.size.cy, OutData.szMmvMsg, lstrlen(OutData.szRbtMsg));
             }
             EndPaint(hWnd, &ps);
             return 0;
          }*/
          case WM_DESTROY:
          {
          	PostQuitMessage(0);
             return 0;
          }
       }
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
    //////////////////////////////////////////////////////////////////////////////////////
    LRESULT CALLBACK ChildProc (HWND hChild, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	static OutputData *pOutData = NULL;
    
    	switch (message)
       {
       	case WM_CREATE:
       	{
    
           	PostMessage(GetParent(hChild), WM_GETDATA, 0, 0);
          	return 0;
          }
          case WM_MOUSEMOVE:
          {
          	switch (wParam)
             {
             	case MK_RBUTTON:
                SendMessage(GetParent(hChild), WM_SENDDATA, LOWORD(lParam), HIWORD(lParam));
                break;
             }
             return 0;
          }
    
          case WM_SENDDATA:
          {  ///////////////////////////////////////////////////////////////////////
          	/*(OutputData*)*/pOutData = (OutputData*)lParam;
             MessageBox(hChild, "WM_SENDDATA angekommen", "Fensternachricht", MB_OK);
             ///////////////////////////////////////////////////////////////////////
             return 0;
          }
          case WM_PAINT:
          {
             PAINTSTRUCT ps;
             HDC			hDC;
    
             char szKeyStatus[40];
             int iKeyLength;
    
             hDC=BeginPaint(hChild, &ps);
             if (pOutData != NULL)
             {
             	for (pOutData->i = 0; pOutData->i<4; pOutData->i++)//F E H L E R
             	{
             		iKeyLength = wsprintf(szKeyStatus, "Status Pfeiltaste %i: %i", pOutData->i, pOutData->ArrowKeys[pOutData->i]);
    
                	GetTextExtentPoint32(hDC, szKeyStatus, iKeyLength, &pOutData->size);
    
                	TextOut(hDC, 1,  pOutData->i * pOutData->size.cy, szKeyStatus, iKeyLength);
                	TextOut(hDC, 1,  5 * pOutData->size.cy, pOutData->szLbtMsg, lstrlen(pOutData->szLbtMsg));
                	TextOut(hDC, 1,  6 * pOutData->size.cy, pOutData->szRbtMsg, lstrlen(pOutData->szRbtMsg));
                	TextOut(hDC, 1,  7 * pOutData->size.cy, pOutData->szMmvMsg, lstrlen(pOutData->szRbtMsg));
             	}
    
             }
             else
             {
             	MessageBox(hChild, "WM_PAINT angekommen", "Fensternachricht", MB_OK);
             }
             EndPaint(hChild, &ps);
             return 0;
          }
          case WM_DESTROY:
          {
          	PostQuitMessage(0);
             return 0;
          }
       }
       return DefWindowProc(hChild, message, wParam, lParam);
    }
    


  • 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..


  • Mod

    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 ^^


Anmelden zum Antworten