JoachimJogi
Mitglied
Mein Programm stürzt regelmäßig ab (assertion), wenn ich die im DEBUG_Modus bin, RELEASE läuft einwandfrei. Ich habe das Problem zurückverfolgt bis zur ersten "ASSERT(ContinueModal());" Zeile im RunModalLoop.
Jetzt frage ich mich, was hat diese Überprüfung für einen Sinn?
In der Releaseversion wird diese Prüfung nicht vorgenommen, und vor allem: Es ist doch ganz normal, dass ContinueModal irgendwann false liefert, oder etwa nicht?
In meinem Programm wird DoModal für eine andere Klasse aufgerufen, danach in einem anderen Thread ein bisschen gerechnet und anschließend aus diesem "anderen" Thread EndModal aufgerufen.
Ich habe schon stundenlang diesen Microsoft Code analysiert, aber komme zu keiner sinnvollen Verwendung für diese Assertions. Weiß einer Rat?
Danke!
Jetzt frage ich mich, was hat diese Überprüfung für einen Sinn?
In der Releaseversion wird diese Prüfung nicht vorgenommen, und vor allem: Es ist doch ganz normal, dass ContinueModal irgendwann false liefert, oder etwa nicht?
In meinem Programm wird DoModal für eine andere Klasse aufgerufen, danach in einem anderen Thread ein bisschen gerechnet und anschließend aus diesem "anderen" Thread EndModal aufgerufen.
Ich habe schon stundenlang diesen Microsoft Code analysiert, aber komme zu keiner sinnvollen Verwendung für diese Assertions. Weiß einer Rat?
Danke!
Code:
int CWnd::RunModalLoop(DWORD dwFlags)
{
ASSERT(::IsWindow(m_hWnd)); // window must be created
ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
HWND hWndParent = ::GetParent(m_hWnd);
m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
MSG* pMsg = &AfxGetThread()->m_msgCur;
// acquire and dispatch messages until the modal state is done
for (;;)
{
ASSERT(ContinueModal());
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
{
ASSERT(ContinueModal());
// show the dialog when the message queue goes idle
if (bShowIdle)
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
// call OnIdle while in bIdle state
if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
{
// send WM_ENTERIDLE to the parent
::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
}
if ((dwFlags & MLF_NOKICKIDLE) ||
!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
{
// stop idle processing next time
bIdle = FALSE;
}
}
// phase2: pump messages while available
do
{
ASSERT(ContinueModal());
// pump message, but quit on WM_QUIT
if (!AfxGetThread()->PumpMessage())
{
AfxPostQuitMessage(0);
return -1;
}
// show the window when certain special messages rec'd
if (bShowIdle &&
(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
if (!ContinueModal())
goto ExitModal;
// reset "no idle" state after pumping "normal" message
if (AfxGetThread()->IsIdleMessage(pMsg))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}
ExitModal:
m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
return m_nModalResult;
}
BOOL CWnd::ContinueModal()
{
return m_nFlags & WF_CONTINUEMODAL;
}
void CWnd::EndModalLoop(int nResult)
{
ASSERT(::IsWindow(m_hWnd));
// this result will be returned from CWnd::RunModalLoop
m_nModalResult = nResult;
// make sure a message goes through to exit the modal loop
if (m_nFlags & WF_CONTINUEMODAL)
{
m_nFlags &= ~WF_CONTINUEMODAL;
PostMessage(WM_NULL);
}
}
Zuletzt bearbeitet: