UpdateData(false); -> Debug Assertion Failed
-
Aus einer fremden Applikation rufe ich einen Dialog aus meiner DLL auf. Diesem Dialog übergebe ich vorher Werte. Um diese Werte nun im Dialog sichtbar zu machen rufe ich UpdateData(false) auf. Nun erhalte ich einen Debug Assertion Failed!
Wenn ich den Dialog allerdings aus einer MFC Test Exe aufrufe erhalte ich diese Meldung nicht. Was mache ich falsch?
-
Es ist nützlich zu wissen an welcher Stelle der ASSERT kracht.
Könnte es sein dass m_hWnd NULL ist und der Diaog noch gar nicht erzeugt ist?
-
Also der Assert ist in wincore.cpp Zeile 900: ASSERT(pMap != NULL);
Das ist der Code dazu
void MyDlg::SetData(const CString &netId, int port) { m_amsNetIdEdit = netId; m_portEdit = port; UpdateData(FALSE); }
bei folgendem Code erhalte ich keinen Fehler
void MyDlg::SetData(const CString &netId, int port) { m_amsNetIdEdit = netId; m_portEdit = port; CWnd *wndnetid = GetDlgItem(IDC_EDIT_AMSNETID); CWnd *wndport = GetDlgItem(IDC_EDIT_PORT); if(wndnetid != NULL && wndport != NULL) { CString csport; csport.Format("%d",m_portEdit); wndnetid->SetWindowText(m_amsNetIdEdit); wndport->SetWindowText(csport); } }
-
Diese Funktion wird vermutich aus einem anderen Thread aufgerufen als dem, der das fenster erzeugt hat.
Fenster sind threadafin und die MFC Klassen sowieso.
-
...threadafin...
Was soll das heißen noch nie gehört. Kenne zwar Affinität, aber threadafin?
Diese Funktion wird vermutich aus einem anderen Thread aufgerufen als dem, der das fenster erzeugt hat.
Ok das kann sein.
Und wie löse ich das Problem nun? Wie in meinem zweiten Code geht es ja aber wenn ich sehr viele Felder setzen will bläht sich der Code unheimlich auf. Andere Möglichkeit?
-
Ein Fenster hat eine Afinität zu einem Thread!
Lösung: Verwende keine anderen Threads. Arbeite nur mit Handles... etc.
-
Ich trau mich ja kaum meine Lösung für solche Probleme hier zu posten..
aber ich machs trotzdemIst allerdings ein 'hack' für UpdateAllViews und wiederspricht so ziemlich allem was man unter sauberer OOP versteht.
#pragma once #define WM_INVOKE WM_APP + 1 // CUpdateAllViews class CUpdateAllViews : private CWnd { DECLARE_DYNAMIC(CUpdateAllViews) public: CUpdateAllViews( CDocument* pDoc ); virtual ~CUpdateAllViews(); private: CDocument* m_pDoc; protected: DECLARE_MESSAGE_MAP() afx_msg LRESULT OnInvoke(WPARAM wParam, LPARAM lParam); public: void Invoke(LPARAM lHint=0, CObject* pHint = NULL, bool bAsync=false); bool Create(CWnd* pParent); };
// UpdateAllViews.cpp: Implementierungsdatei // #include "stdafx.h" #include "UpdateAllViews.h" // CUpdateAllViews IMPLEMENT_DYNAMIC(CUpdateAllViews, CWnd) CUpdateAllViews::CUpdateAllViews( CDocument* pDoc ) : m_pDoc( pDoc ) { } CUpdateAllViews::~CUpdateAllViews() { DestroyWindow(); } bool CUpdateAllViews::Create(CWnd* pParent) { if( pParent ) { if( CWnd::Create( NULL, NULL, WS_CHILD, CRect(), pParent, 10001 ) ) return true; } return false; } void CUpdateAllViews::Invoke(LPARAM lHint, CObject* pHint, bool bAsync) { if( m_hWnd ) { if( bAsync ) PostMessage( WM_INVOKE, reinterpret_cast <WPARAM> ( pHint ), lHint ); else SendMessage( WM_INVOKE, reinterpret_cast <WPARAM> ( pHint ), lHint ); } } BEGIN_MESSAGE_MAP(CUpdateAllViews, CWnd) ON_MESSAGE( WM_INVOKE, CUpdateAllViews::OnInvoke ) END_MESSAGE_MAP() // CUpdateAllViews-Meldungshandler LRESULT CUpdateAllViews::OnInvoke(WPARAM wParam, LPARAM lParam) { m_pDoc->UpdateAllViews( NULL, lParam, reinterpret_cast < CObject* > ( wParam ) ); return 0L; }
Eine Instanz von CUpdateAllViews wird im Doc erzeugt, damit lassen sich aus anderen Threads Funktionen des Docs aufrufen, die dann über m_updateAllViews.Invoke() eben UpdateAllViews aufrufen. Dabei wird allerdings ein unsichtbares Fenster erstellt welches dann die Nachrichten weitergibt.
Bevor mich jetzt jemand haut.. *duck und weg*
-
Lösung: Verwende keine anderen Threads. Arbeite nur mit Handles... etc.
Darauf habe ich keinen Einfluss. Habe eine DLL geschrieben die von einer Anwendung verwendet wird. In InitInstance() wird der Dialog erzeugt mit Create. Mit einer Exportfunktion die auch wieder von der externen Applikation aufgerufen wird, wird auch unter anderem die Funktion UpdateData(false) aufgerufen.
Wie soll ich hier nun vorgehen?
-
Sicher hast Du Einfluss!
Ruf eben nicht UpdateData auf!In Deiner MFC Anwednung sind auch nur Handles.
Mach es mit der Windows API und es geht.
-
Sondern ich rufe was auf. Sorry aber ich habe gerade keine Idee wo ich nun angreifen soll.
-
SetWindowText... etc. Am Besten liest Du Dich ein wenig in die Windows API ein...
-
SetWindowText habe ich doch schon verwendet. Aber dazu habe ich ja auch meine Bedenken geäussert.
Und desweiteren ist das aber nicht der Lösungsansatz den du mir zuerst geraten hast:
Verwende keine anderen Threads. Arbeite nur mit Handles... etc.
-
visualer schrieb:
SetWindowText habe ich doch schon verwendet. Aber dazu habe ich ja auch meine Bedenken geäussert.
Und desweiteren ist das aber nicht der Lösungsansatz den du mir zuerst geraten hast:
Verwende keine anderen Threads. Arbeite nur mit Handles... etc.
Bedenken? Wo hast Du Bedenken geäußert?
Du hast SetWindowText wieder verwendet und nimmst wiederum MFC Objekt, die threadafin sind, also nur gültig sind im Thread, der Sie erzeugt hat?
Woher soll ich bitte wissen, dass Deine Anwednung aus beliebigen Threads kruz und quer Deine Anwendung aufruft.
Hast Du gesagt, dass Du keine Kontrolle hast über die Anwednung? Nein!Verwende keine Cross-Thread-Calls ist die einfachste Lösung. Punkt!
Wenn Du Herr (Codeowner) der Applikationen bist, kannst Du auch dafür sorgen!Meine Glaskugel steht bei mir zu Hause auf dem Fensterbrett. Hier bei der Arbeit habe ich keine...
-
Also aus deinen Meldungen werde ich nicht schlau.
Bedenken? Wo hast Du Bedenken geäußert?
Ich habe ein Beispiel mit SetWindowText gebracht und habe gemeint dass dies meinen Code aufbläht.
Du hast SetWindowText wieder verwendet...
Ist das nun ein Vorwurf. Hast doch selber vorher gesagt ich soll es verwenden:
SetWindowText... etc. Am Besten liest Du Dich ein wenig in die Windows API ein...
Hast Du gesagt, dass Du keine Kontrolle hast über die Anwednung? Nein!
Doch habe ich.
Meine Glaskugel steht bei mir zu Hause auf dem Fensterbrett.
Aber lesen sollte man am Arbeitsplatz können oder das Hirn auch auf der Fensterbank gelasen.
Vergiss es. Man hat mich schon gewarnt vor deinen komischen Aussagen.
-
Um das ganze mal zu entschärfen. Und entschudligung das ich mich hier auch einmische. Habe das ganze auch verfolgt und habe ein ähnliches Problem.
Was ich aber auch nicht ganz verstanden habe: Soll nun SetWindowText() verwendet werden oder nicht?
-
Es gibt SetWindowText() (API) und es gibt CWnd::SetWindowText() (MFC)!
-
gute nacht johni schrieb:
Um das ganze mal zu entschärfen. Und entschudligung das ich mich hier auch einmische. Habe das ganze auch verfolgt und habe ein ähnliches Problem.
Was ich aber auch nicht ganz verstanden habe: Soll nun SetWindowText() verwendet werden oder nicht?
Es sollen nach möglichkeit KEINE MFC Funktionen verwendet werden, sondern Windows API. Also SetWndowText!
Was ist daran unklar?Genau wie connan schreibt! Es gibt SetWindowText mehrfach
-
visualer schrieb:
Vergiss es. Man hat mich schon gewarnt vor deinen komischen Aussagen.
Jo! Und tschüss!
-
Es gibt SetWindowText() (API) und es gibt CWnd::SetWindowText() (MFC)!
Achso jetzt wird mir das klar.
Darf ich jetzt auch nochmal was fragen. Wenn ich nun in meiner Dialogklasse SetWindowText aufrufe dann verwende ich ja die von MFC. Wie greife ich nun aber auf die Api Funktion zu.
-
Also was ich bereits gemacht habe ist "Windows.h" included. So wenn ich nun aber SetWindowText() aufrufe wird immer noch auf die SetWindowText der MFC verwendet.
Muss ich da noch was definieren?
-
Hallo,
eine C++-Grundlagenforschung würde ergeben: Man verwendet den ::-Operator, um auf solche Funktionen zuzugreifen.
MfG,
Probe-Nutzer