AfxBeginThread - error C2597



  • Ich hab folgendes Problem:
    Ich muss in meiner MFC Anwendung Multithreading anwenden.
    Ich starte den Thread über AfxBeginThread:

    void CProgrammDlg::OnBnClickedStart()
    {
    
    	LPVOID * pParam;
    
    	UpdateData (TRUE);
    	m_strLeuft_seit = curTime.Format ("%H:%M:%S");
    	UpdateData(FALSE);
    
    	AfxBeginThread (StartWriting, (LPVOID) & pParam);
    
    }
    
    UINT CProgrammDlg::StartWriting(LPVOID pParam)
    {
            UpdateData (TRUE);
            // Verarbeitung
    }
    

    Das Problem ist hierbei das sowohl eine fehlermeldung bei "static UINT ..." kommt, da

    1>c:\users\...\Programm.cpp(220) : error C2352: 'CWnd::UpdateData': Unzulässiger Aufruf einer nicht statischen Memberfunktion
    

    als auch wenn ich nur "UINT.." habe, da

    1>c:\users\...\Programm.cpp(205) : error C3867: "CProgrammDlg::StartWriting": Dem Funktionsaufruf fehlt die Argumentliste. Verwenden Sie "&CProgrammDlg::StartWriting", um einen Zeiger auf den Member zu erstellen.
    

    😞

    Ich komm hier nicht weiter.
    Am liebsten wäre es mir wenn StartWriting nicht statisch wäre, da es sonst konfilikte mit ein paar globalen variablen gibt.
    Gegooglet hab ich au schon, aber nichts nützliches gefunden. 😞

    Hoffe mir kann einer weiterhelfen

    PS: Ich kenn mich auf dem gebiet C++/MFC noch nicht so gut aus.



  • Die Funktion muss static sein. static bedeutet die Funktion ist eine "normale" Funktion und keine Memberfunktion. Das heisst die Funktion ist nicht an ein bestimmtes Objekt gebunden. Deshalb kannst du auch auf keine Member-Variablen oder Memberfunktionen zugreifen.
    Lösung: ein Objekt als Paramemter übergeben.
    z.B.

    void CProgrammDlg::OnBnClickedStart()
    {
    
        LPVOID * pParam = this;
    
        UpdateData (TRUE);
        m_strLeuft_seit = curTime.Format ("%H:%M:%S");
        UpdateData(FALSE);
    
        AfxBeginThread (StartWriting, (LPVOID) & pParam);
    
    }
    
    UINT CProgrammDlg::StartWriting(LPVOID pParam)
    {
            CProgrammDlg* object = reinterpret_cast<CProgrammDlg*>(pParam);
            object->UpdateData (TRUE);
            // Verarbeitung
    }
    

    Es ist aber tödlich aus einem (anderen) Thread auf Funktionen der Gui zuzugreifen.
    Du musst aus dem Thread Nachrichten mit SendMessage / PostMessage an den Gui Thread versenden. Der Gui Thread aktualisiert dann die Controls.



  • Danke für die schnelle antwort, dennoch scheint da was noch nicht ganz zu stimmen.

    void CProgrammDlg::OnBnClickedStart()
    {
    
        LPVOID * pParam = this;
    
        UpdateData (TRUE);
        m_strLeuft_seit = curTime.Format ("%H:%M:%S");
        UpdateData(FALSE);
    
        AfxBeginThread (StartWriting, (LPVOID) & pParam);
    
    }
    
    UINT CProgrammDlg::StartWriting(LPVOID pParam)
    {
            CProgrammDlg* object = reinterpret_cast<CProgrammDlg*>(pParam);
            object->UpdateData (TRUE);
            // Verarbeitung
    }
    

    Zu Linie 4 kommt volgende fehlermeldung:

    1>c:\users\...\Programm.cpp(197) : error C2440: 'Initialisierung': 'CProgrammDlg *const ' kann nicht in 'LPVOID *' konvertiert werden
    

    Wenn ich aber den dereferenzierungs Operator (*) wegnehme, kompiliert er zwar, das Programm gibt aber bei der ausführung den geist auf 😞



  • Da sind ein paar * und & zuviel. Nur LPVOID pParam.
    und bei der Übergabe an AfxBeginThread nur pParam übergeben. Cast und & brauchst du nicht bzw. das & ist falsch.

    Du darfst UpdateData nicht in einem anderen Thread verwenden oder in sonst irgendeiner Art auf Controls zugreifen. Du musst stattdessen SendMessage oder PostMessage verwenden und im Gui Thread die Control aktualisieren (oder was auch immer).



  • kannst du mir bitte ein kleines beispiel nennen wie ich die gui aktualisieren kann.



  • http://vcfaq.mvps.org/mfc/12.htm
    Google ist für sowas ideal. Das Netz ist voll mit solchen Beispielen.



  • danke für die schnellen antworten, aber leider kann ich mit dem link nichts anfangen (Steht einer auf meiner leitung??????)
    warscheinlich steh ich for der antwort seh sie aber net 😞
    kannst du mir vllt die lücke ausfüllen, bitte?

    UINT CProgrammDlg::StartWriting(LPVOID pParam)
    {
            // Lücke, hier kommt die aktualiesierung mit der gui hin
            // Verarbeitung
    }
    


  • Aber die Anleitung ist doch Klasse,, du gibst deinem Thread das Handel auf dein Window mit, im Thread Sendest du mit PostMessage eine UserNachricht an das Window, Diese erhält die Nachricht um Ruft deine Routine Per Defininition aus der MessageMap auf, und in deiner Routine Kannst du die ganzen Sachen deiner GUI aktualisieren, und wenn de willst, kannste auch die Daten die Aktualisiert werden sollen mitschicken (LPARAM), oder ein Flag (WPARAM) oder sonnst was



  • ich könnt heulen 😞
    ich bin net so gut in englisch, und das da auf der seite blick ich garnet 😕
    ich erkenn solche sachen immer schnell an einem kleinen beispiel, ist das zuviel verlangt?

    bitte



  • Da Versuch ich das mal für den Bettler schnell auf deutsch zu erklären 😉

    1. #define MY_WM_MESSAGE1 (WM_APP + 1)
    eine neue Machrichten-Definition für die Message-Map erstellen, kann zum beispiel in der StdAfx.h erfolgen

    2. ::PostMessage(hwnd, MY_WM_MESSAGE1, (WPARAM)0, (LPARAM)0);
    oder,
    ::SendMessage(hwnd, MY_WM_MESSAGE1, (WPARAM)0, (LPARAM)0);
    in deinem Thread an der stelle schreiben wo du dein Window aktualisieren lassen willst, wenn du die nachrichtenbestätigung nich benötigst dann benutze PostMessage, erspaart auch noch ärger mit anderen effekten die bei SendMessage entstehen könnten

    3. afx_msg LRESULT OnMyMessage1(UINT wParam, LONG lParam);
    in dem Header deines Wondows definieren, das wird dann deine Nachrichtenbehandlungs-Routine

    4. //}}AFX_MSG_MAP
    ON_MESSAGE(MY_WM_MESSAGE1, OnMyMessage1)
    END_MESSAGE_MAP()

    Message in der Message-Map definieren, damit wenn die Nachricht eintrifft auch dein OnMyMessage1 ausgeführt wird,Achtung erst nach //}}AFX_MSG_MAP schreiben, da sonnst VisualSTudio bei den nächsten einfügen das eventuell weg schmeißt

    5. LRESULT CMainFrame::OnMyMessage1(UINT wParam, LONG lParam)
    {
    ... do something about the message from secondary thread
    return 0; // I handled this message
    }
    die Message-Funktion und hier darf sich dann ausgetobt werden und alles was mit GUI zu tun hat auch durchgeführt werden

    Hoffe das es jetzt verständlich ist



  • Danke,
    ich hoffe ich bekomm das jetzt hin.
    Hatte vergangene Woche leider keine Zeit gehabt hier mal rein zu schauen, was mir leid tut, da ich natürlich rückmeldung geben möchte! 😉
    Ich bedanke mich bei allen die sich um mein Interresse bemüht haben 🙂

    Ich werde mich melden wenn ich noch fragen habe 😃 :p



  • Oh je,
    Also bis auf punkt 4 blick ichs schon irgendwie.
    Bin halt neu im Geschäft 😛 .
    Wo kommt der 4te Punkt hin?



  • Hallo,

    dort, wo dein "Hauptfenster" (bei dir ein Dialog) definiert wird, befindet sich die sogenannte "Message-Map", sie wird von BEGIN_MESSAGE_MAP und END_MESSAGE_MAP() eingeschlossen. Suche einfach danach (ist gut, das selber zu inspizieren, um mit dem Aufbau vertraut zu werden), und platziere den Eintrag

    ON_MESSAGE(MY_WM_MESSAGE1, OnMyMessage1)
    

    hinter

    //}}AFX_MSG_MAP
    

    (das ist das Ende-Kennzeichen für Code, der von Assistenten eingefügt wird, deswegen sollte die obige Zeile nicht innerhalb der
    AFX_MSG_MAP-Kennzeichnug stehen)

    aber noch innerhalb der oben genannten "Begrenzer".

    MfG,

    Probe-Nutzer


Anmelden zum Antworten