Zugriff aus Thread auf Controls



  • Dann hat MFK Mist erzählt!
    Entweder du arbeitest mit Handles und API Funktionen,oder du leitest ne threadsichere Klasse ab und arbeitest mit Attach,Detach oder du sendest benutzerdefinierte Nachrichten an dein Window und läßt dein Window darauf reagieren.

    MfG Spacelord



  • Kann man dazu vielleicht mal einen kleinen Quelltextausschnitt bekommen um das mal zu sehn?

    Wäre für ein kleines Beispiel dankbar.

    Was ist denn besser welche Methode?

    Grüße



  • thodtie schrieb:

    Kann man dazu vielleicht mal einen kleinen Quelltextausschnitt bekommen

    Threadcode...

    UINT StatusBarUpdaterThreadFunc(LPVOID data){
      DLG_Transfer* pDlgTrans = (DLG_Transfer*)data;
    
      if(pDlgTrans!=NULL){ 
    
        pDlgTrans->m_ProgressBar.SetRange(0, 6);
        pDlgTrans->m_ProgressBar.SetStep(1);
    
        for(int i=0; i<6; i++){
          pDlgTrans->m_ProgressBar.StepIt();
        }
      }
      return 0
    }
    

    und gestartet wird dann mit:

    AfxBeginThread(StatusBarUpdaterThreadFunc, (LPVOID)this, THREAD_PRIORITY_NORMAL);
    

    DLG_Transfer ist meine Dialogklasse, aus welcher ich beim OnClick die AfxBeginThread Methode aufrufe. Da ich mittels dem Thread auf die Variable von DLG_Transfer zugreiffen will (z.B. eben auf den CProgressCtrl), gebe ich 'LPVOID)this' mit, ansonsten halt anstatt 'this' das entsprechende Objekt mitgeben.

    So funktionierts bei mir jedenfalls.



  • Das ist ein Tanz auf dem Vulkan aber egal....

    MfG Spacelord



  • wieso?



  • Ich habs bisher immer so gemacht dass ich eine normale Funktion aus der Threadfuntkion aufgerufen hab und der dann die Parameter übergeben. Beispiel:

    UINT CRouteSortDlg::ProcessCopyingThread(LPVOID pParam)
    {
    	CRouteSortDlg* pDlg = (CRouteSortDlg*) pParam;
        ...
    	pDlg->SetProgressStatus(nF);
        ...
    
    	return 0;
    }
    
    /**************************************************************************************************************************/
    /**************************************************************************************************************************/
    
    void CRouteSortDlg::SetProgressStatus(int currentStatus)
    {
    	m_ctlProgressStatus.SetRange(0, maximalRange);
    
    	if(currentStatus == (maximalRange - 1)) m_ctlProgressStatus.SetPos(maximalRange);
    	else									m_ctlProgressStatus.SetPos(currentStatus);
    }
    

    Hat bisher gut geklappt, ist das auch ein Tanz auf dem Vulkan?



  • Ich würd sagen, ist genau dasselbe, bloß das du eben eine Funktion aufruftst, die eben in der Dialogklasse liegt. Ich hab das Steuerelement so angesteuert.

    Wie kann ich denn am besten einen Thread von außen beenden?

    Grüße



  • Wenn du den Pointer auf den Dialog in dem fremden Thread benutzt läufst du akut Gefahr eine der 1000000 Million ASSERT Bedingungen die in den MFC intern verborgen sind zu verletzen.
    Um ein grundlegendes Verständnis für dass Problem ansich zu bekommen solltest du dir erstmal diesen hervorragenden Artikel durchlesen:
    http://www.mindfiresolutions.com/download/Inside%20MFC=Handle%20Maps%20and%20Temporary%20Objects.pdf

    Wenn dir das dann klar ist kannst du mal hier schauen ist in etwa dass was du auch wissen möchtest:
    http://www.fun-soft.de/showtopic.php?threadid=9273&post_start=0&time=1100189956

    Les dir das erstmal alles durch,dann solltest du schon etwas weiter sein.
    Das ist nicht so mal eben erklärt...

    MfG Spacelord



  • Wenn's irgend geht ist prinzipiell besser aus einem Thread heraus Nachrichten an den Hauptdialog zu senden und nicht direkt drauf zuzugreifen. Im Fall des Progresscontrols z.B. so:

    UINT CMyDlg::thrTest(LPVOID pParam)
    {
    	int nRet = 0;
    	int nCounter = 0;
    	CMyDlg* pDlg = (CMyDlg*)pParam;
    	HWND hWnd = pDlg->m_hWnd;
    	HWND hProgCtrl = ::GetDlgItem(hWnd,IDC_PROGRESS);
    	::SendMessage(hProgCtrl,PBM_SETRANGE,(WPARAM)0,(LPARAM) MAKELPARAM(0, 100)); //Die Range des Progresscontrols setzten
    	while (nCounter < 100)
    	{
    		::SendMessage(hProgCtrl,PBM_SETPOS,(WPARAM)++nCounter,0); // Das Progresscontrol hochzählen
    	}
    
    	::SendMessage(hProgCtrl,PBM_SETPOS,(WPARAM)0,0);
    	::PostMessage(hWnd, WM_USER_MESSAGE_FINISHED, (WPARAM)nRet, 0);
    	return (UINT)0;
    }
    

    Gruß T. 🙂



  • 👍
    So ist es...
    In dem Thread dessen Link ich gepostet hab,hab ich auch die Lösung über benutzerdefinierte Nachrichten gewählt.Mag ich persönlich am ehesten.Kommt aber immer auf den konkreten Fall drauf an.
    Trotzdem sollte der Fragesteller sich erstmal durchlesen wo überhaupt das Problem liegt!

    MfG Spacelord



  • Ok super danke, werd ich durchlesen sobald ich Zeit finde.


Anmelden zum Antworten