Problem mit Threads und CWnds



  • Hi,
    Ich hab grad ein ziemlich derbes Problem:
    Ich hab nen Dialog (abgeleitet von CDialog), welcher unter anderem zwei Membervariablen hat. Eine dieser Variablen (Var1) ist direkt per MessageMap mit einem Control verbunden. Der Typ dieser Variable ist öffentlich von CStatic abgeleitet.
    Die zweite Variable (Var2) wird indirekt ein wenig mit einem zweiten Control verbunden:
    Sie hat eine Funktion, der man ein CWnd* und eine ID übergibt. Die ID ist die ID des zweiten Controls und dort erscheint die Ausgabe der Klasse. Das CWnd* wird intern als Parent gespeichert. Die Klasse ist von CWnd abgeleitet.
    In der Dialogklasse wird ein Thread mit AfxBeginThread gestartet. Thread-Parameter ist der this-Zeiger der Dialogklasse.
    In der Threadfunktion werden gewisse Methoden der Dialogklasse und von Dialogklasse->Var2 aufgerufen - funktioniert problemlos.
    Ausserdem wird eine Methode von Dialogklasse->Var1 aufgerufen. In dieser Methode wird ein CPaintDC-Objekt mit dem this-Zeiger erzeugt. Und da bekomm ich nen Assert:

    CObject* p;
            ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
                (p = pMap->LookupTemporary(m_hWnd)) != NULL);
    

    Der Assert steht in CWnd::AssertValid (WINCORE.CPP, Zeile 881ff)

    Drunter steht noch der Kommentar:

    // Note: if either of the above asserts fire and you are
            // writing a multithreaded application, it is likely that
            // you have passed a C++ object from one thread to another
            // and have used that object in a way that was not intended.
            // (only simple inline wrapper functions should be used)
            //
            // In general, CWnd objects should be passed by HWND from
            // one thread to another.  The receiving thread can wrap
            // the HWND with a CWnd object by using CWnd::FromHandle.
            //
            // It is dangerous to pass C++ objects from one thread to
            // another, unless the objects are designed to be used in
            // such a manner.
    

    Das habe ich auch schon probiert (HWND übergeben und dann FromHandle im Thread benutzen). Hat nicht geklappt, dann stürzt das Programm mit nem Zugriffsfehler ab, wenn ich auf Membervariablen der Dialogklasse zugreifen will.

    Hat jemand ne Idee, was ich da noch machen könnte ???
    Ich weiss echt net mehr weiter 😞
    Danke fürs durchlesen.

    [ Dieser Beitrag wurde am 04.09.2002 um 18:49 Uhr von dEUs editiert. ]



  • Hab das Problem das ich das ganze nicht reproduzieren kann. Da hast also eine CDialog, die als Atribute eine von CDialog und einer von CWnd anbgeleitet Klasse hat? Und nun übergibts du nen Thread nen Zeiger auf die erste CDialog und versucht auf die CWnd zuzugreifen?
    Hast du etwas Code?

    Ich habs mal so versucht, hat alles hingauen:

    class CVar1 : public CDialog
    {
    ...
    }
    
    class CVar2 : public CWnd
    {
    pulbic:
    void set(CDialog *dlg,long ID);
    ..
    private:
    CDialog *lpDlg;
    long iID;
    ..
    }
    
    class CTestDlg : public CDialog
    {
    public:
    CVar1 var1;
    CVar2 var2;
    static UINT TheThread(LPVOID lp);
    ....  
    }
    
    void CTestDlg::OnButton1() 
    {
      AfxBeginThread(TheThread,this);
    }
    

    Und im Thread rufe ich ne Methode von var1 und eine von var2 auf. In der set-Methode von var2 kommt auch ein CPaintDC vor.
    Mach ich was anders, oder warum geht das bei mir? :p

    Wenn du es wirklich nicht zum laufen bekommst, gibt es noch massenweise andere Funktionen zur Threadkomunikation... aber wenigstens über das HWND müssten wirs schon zum laufen bekommen.

    Also was mach ich anders? Kannst etwas Code ins Forum schmuggeln? 😃

    [ Dieser Beitrag wurde am 05.09.2002 um 08:51 Uhr von CMatt editiert. ]



  • Hmm ... Ich habs jetzt anders gemacht:
    Ich hab den PaintDC nur dazu benutzt CompatibleDCs und Bittmaps zu erzeugen. Hab den PaintDC jetzt einfahc durch GetDC() ersetzt und das klappt 😉


Log in to reply