Threading problem...



  • Hi,

    wie ich das jetzt mitbekommen habe, darf ich kein MFC Fenster-Objekt einfach an einen Thread weitergeben, sondern nur das Fensterhandle aus dem sich der Thread dann wieder ein MFC Objekt erstellen kann. Jetzt habe ich allerdings das Problem, das ich ein abgeleitetes MFC Fensterobjekt habe, bei dem neue Eigenschaften direkt an dem Fensterobjekt und nicht an dem Fenster selbst gespeichert werden.... und nun?

    Vielen dank schonmal im voraus für jede Hilfe
    template



  • Was genau brauchst Du in Deinem Thread? Ein Fenster oder bestimmte Elemente, die Du in Deiner abgeleiteten Fenster-Klasse hast?
    Falls Du wirklich beides brauchen solltest, dann kannst Du z.B. eine Struktur anlegen, in der Du das Handle des Fensters und zusätzliche Infos ablegen kannst.



  • Hi,

    vielen dank für die schnelle Antwort. Ich brauche leider beides, weil eigenschaften die das verhalten meines abgeleiteten MFC Objektes beieenflussen am MFC Objekt und nicht am Fenster festgehalten sind. Das Problem ist das ich die werte auch nicht einfach by value zum Thread kopieren kann, da diese sich ja während der Laufzeit des Threads ändern können.

    Bsp:

    class CNeuerButton : public CButton
    {
    public:
      SetImages(HBITMAP hPushed, HBITMAP hNonPushed);
      /* Überschriebene Routine */
      OnDraw(....);
    
    private:
      HBITMAP m_hPushedImage;
      HBITMAP m_hNonPushedImage;
    }
    


  • wie ich das jetzt mitbekommen habe, darf ich kein MFC Fenster-Objekt einfach an einen Thread weitergeben, sondern nur das Fensterhandle aus dem sich der Thread kann wieder ein MFC Objekt erstellen kann.

    Warum?



  • Ein Worker-Thread sollte nie auf GUI-Controls zugreifen. Sieht mir nach einem Designproblem bei Dir aus.

    Wenn der Thread Daten aus GUI-Controls lesen muss, dann führt der Weg über eine eigene Datenstruktur (ein struct oder eine Klasse), die sich beide Threads teilen(zu schützen mit CriticalSections). Die Membervar's Deines Buttons, die sich beide Threads teilen, sollten in eine solche Datenstruktur verschoben werden.

    Wenn der Thread GUI-Controls verändern muss, dann ist der beste Weg eine eigene Message zu definieren, die der Thread an den GUI-Thread mittels PostMessage sendet.



  • da kann ich nickhappy zustimmen,

    Du Musst in deinem Thread mit PostThreadMessage eine Nachricht an den Dlg senden. Dazu musst du im Dlg noch dir die WindowProc Funktion zulegen und im App dafür sorgen das die Messages aus deinem Thread auch zum WindowProc kommen.

    Wenn du Speicher im WorkerThread allozierst und Pointer an den Dlg gibts und er sie dann auch wieder löschen sollte musst du aufpassen das der Dlg nicht grad blockt (zB MessageBox) dann würde die Message allerdings nicht ankommen und Memory Leak angeben.

    APP:

    BOOL  CmyApp::PreTranslateMessage(MSG* pMsg)
    	{
    		// Is it the Message you want?
    		// You can use a switch statement but because this is
    		// only looking for one message, you can use the if/else
    		if (pMsg->message == ID_LASTCONTROL +1) // da dir was definieren <--
    		{
    			// Call the function to handle this message
    			this->m_pMainWnd->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
    			// Tell MFC no more processing is needed
    			return TRUE;
    		}
    		else
    			// Call MFC to have it continue processing the message
    			return CWinThread::PreTranslateMessage(pMsg);
    	}
    

    DLG:

    LRESULT CmyDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    	if(message == ID_LASTCONTROL + 1) {
    		switch (wParam) {
    			case UPDATE_XXX:
    				if(lParam != NULL) {
    					GetDescendantWindow(IDC_METADATA)->SetWindowText((TCHAR*)lParam);
    					delete [] (TCHAR*)lParam;
    				}
    				break;
    			case UPDATE_METABUFFER:
    				if(lParam != NULL) {
    					GetDescendantWindow(IDC_METADATABUFFER)->SetWindowText((TCHAR*)lParam);
    					delete [] (TCHAR*)lParam;
    				}
    				break;
    			case UPDATE_BUFFERPER:
    				((CProgressCtrl*)GetDescendantWindow(IDC_PROGRESS1))->SetRange(0, 100);
    				((CProgressCtrl*)GetDescendantWindow(IDC_PROGRESS1))->SetPos((unsigned) lParam);
    
    				break;
    		}
    		return TRUE;
    	} else {
    		return CDialog::WindowProc(message, wParam, lParam);
    	}
    }
    

    Thread:

    unsigned WINAPI	CmyThread::dowork(void* mythread) {
    	CmyThread* thisthread = (CmyThread*)mythread;
    
    	WPARAM paramw = MAKEWPARAM(0,0);
    	LPARAM paraml = MAKELPARAM(0,0);
    
    	while(!thisthread->doexit()) {
    		{
                      // Weiterer Thread von mir für Datenhaltung
    			CAuLck lock(thisthread->sthreadlock);
    			CSocketThread* thissocket = (*thisthread->sthread);
    
    			if(thissocket != NULL) {
    				BOOL success = FALSE;
    				// Radio
    				TCHAR *rname = NULL, *rgenre = NULL;
    				if(thissocket->GetServerInfo(&rgenre, &rname)) {
    					if(rname != NULL) {
    						success = PostThreadMessage(thisthread->uithreadid, thisthread->msgstart+1, (WPARAM)UPDATE_NAME, (LPARAM) rname);
    						if(!success)
    							delete [] rname;
    					}
    
    					if(rgenre != NULL) {
    						success = PostThreadMessage(thisthread->uithreadid, thisthread->msgstart+1, (WPARAM)UPDATE_GENRE, (LPARAM) rgenre);
    						if(!success)
    							delete [] rgenre;
    					}
    				} else {
    					if(rgenre != NULL)
    						delete [] rgenre;
    					if(rname != NULL)
    						delete [] rname;
    				}
    
    				// Metadaten
    				TCHAR *mtitle = NULL;
    				if(thissocket->GetMetaData(&mtitle)) {
    					if(mtitle != NULL) {
    						success = PostThreadMessage(thisthread->uithreadid, thisthread->msgstart+1, (WPARAM)UPDATE_META, (LPARAM) mtitle);
    						if(!success)
    							delete [] mtitle;
    					}
    				} else {
    					if(mtitle != NULL)
    						delete [] mtitle;
    				}
    
    				// buffer
    				unsigned per = 0;
    				if(thissocket->GetBufferPerce(per)) {
    					PostThreadMessage(thisthread->uithreadid, thisthread->msgstart+1, (WPARAM)UPDATE_BUFFERPER,	(LPARAM) per);
    				}
    
    			}
    		}
    		Sleep(250);
    	}
    	return 0;
    };
    

Anmelden zum Antworten