ghimireniraj
asked on
UpdateAllViews crash Problem
extern CMainApp theApp;
UINT __cdecl MyThread( LPVOID pParam );
the thread is started with AfxBeginThread(......)
in the thread functions
UINT __cdecl MyThread( LPVOID pParam )
{
while(done == FALSE)
{
result = WaitForMultipleObjects(num Handles, pWaitHandles, FALSE,
THREAD_WAIT_TIMEOUT); //used to be INFINITE
handleIndex = result - WAIT_OBJECT_0;
switch(handleIndex)
{
case 0:
//Happens every 1 second
bResult = theApp.PostThreadMessage(W M_UPDATE_V IEWSETA, 0, 0);
break;
case 1:
//Happens every 2 Seconds
bResult = theApp.PostThreadMessage(W M_UPDATE_V IEWSETB, 0, 0);
break;
//Happens every 10 milliSeconds
case 2:
bResult = theApp.PostThreadMessage(W M_UPDATE_V IEWSETC, 0, 0);
break;
:
:
}
}
On recieving each of these messages UpdateAllViews is called with different hints hence OnUpdate for all views are called and will update if matching hint is recieved.
I am not passing any window handles across threads.
ViewA1::OnUpdate()
{
}
ViewA2::OnUpdate()
{
}
ViewA3::OnUpdate()
{
}
ViewB1::OnUpdate()
{
}
ViewB2::OnUpdate()
{
}
ViewB3::OnUpdate()
{
}
ViewC1::OnUpdate()
{
}
ViewC2::OnUpdate()
{
}
ViewC3::OnUpdate()
{
}
My Problem is
When the messages WM_UPDATE_VIEWSETA,WM_UPDA TE_VIEWSET B and WM_UPDATE_VIEWSETC are being at 1,2 secs and 10 milisecs respectively, all views update fine.
Now if I close a open View say ViewB1, then the program crashes.
Looking at the call stack, it crashes at
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
ENSURE(this != NULL);
// it better be in valid memory, at least for CObject size
->> ASSERT(AfxIsValidAddress(t his, sizeof(CObject)));
// simple SI case
CRuntimeClass* pClassThis = GetRuntimeClass();
ENSURE(pClassThis);
return pClassThis->IsDerivedFrom( pClass);
}
This is being called by
CView* CDocument::GetNextView(POS ITION& rPosition) const
{
ASSERT(rPosition != BEFORE_START_POSITION);
// use CDocument::GetFirstViewPos ition instead !
if (rPosition == NULL)
return NULL; // nothing left
CView* pView = (CView*)m_viewList.GetNext (rPosition );
--> ASSERT_KINDOF(CView, pView);
return pView;
}
And the view is the ViewB1...Which has already been closed.
I checked step executing at the destructor , the CDocument::RemoveView() is being called for the view being removed.
Closing the view interrupts UpdateAllViews at the middle of its calls, nulls the window pointers for that view. When execution resumes back it UpdateAllViews application crashes. Wierd that MFC is supposed to synchronize this operation.
How can this happen?
Thanks
UINT __cdecl MyThread( LPVOID pParam );
the thread is started with AfxBeginThread(......)
in the thread functions
UINT __cdecl MyThread( LPVOID pParam )
{
while(done == FALSE)
{
result = WaitForMultipleObjects(num
THREAD_WAIT_TIMEOUT); //used to be INFINITE
handleIndex = result - WAIT_OBJECT_0;
switch(handleIndex)
{
case 0:
//Happens every 1 second
bResult = theApp.PostThreadMessage(W
break;
case 1:
//Happens every 2 Seconds
bResult = theApp.PostThreadMessage(W
break;
//Happens every 10 milliSeconds
case 2:
bResult = theApp.PostThreadMessage(W
break;
:
:
}
}
On recieving each of these messages UpdateAllViews is called with different hints hence OnUpdate for all views are called and will update if matching hint is recieved.
I am not passing any window handles across threads.
ViewA1::OnUpdate()
{
}
ViewA2::OnUpdate()
{
}
ViewA3::OnUpdate()
{
}
ViewB1::OnUpdate()
{
}
ViewB2::OnUpdate()
{
}
ViewB3::OnUpdate()
{
}
ViewC1::OnUpdate()
{
}
ViewC2::OnUpdate()
{
}
ViewC3::OnUpdate()
{
}
My Problem is
When the messages WM_UPDATE_VIEWSETA,WM_UPDA
Now if I close a open View say ViewB1, then the program crashes.
Looking at the call stack, it crashes at
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
ENSURE(this != NULL);
// it better be in valid memory, at least for CObject size
->> ASSERT(AfxIsValidAddress(t
// simple SI case
CRuntimeClass* pClassThis = GetRuntimeClass();
ENSURE(pClassThis);
return pClassThis->IsDerivedFrom(
}
This is being called by
CView* CDocument::GetNextView(POS
{
ASSERT(rPosition != BEFORE_START_POSITION);
// use CDocument::GetFirstViewPos
if (rPosition == NULL)
return NULL; // nothing left
CView* pView = (CView*)m_viewList.GetNext
--> ASSERT_KINDOF(CView, pView);
return pView;
}
And the view is the ViewB1...Which has already been closed.
I checked step executing at the destructor , the CDocument::RemoveView() is being called for the view being removed.
Closing the view interrupts UpdateAllViews at the middle of its calls, nulls the window pointers for that view. When execution resumes back it UpdateAllViews application crashes. Wierd that MFC is supposed to synchronize this operation.
How can this happen?
Thanks
ASKER
Thanks Dan for your suggestions. Sorry I was out for few days and could not respond immediately.
>>>The posted messages are probably piled up in the queue, and one of the OnUpdate() calls is being executed during a moment in which the CView-derived object still exists, but the window it encapsulates does not.
How would I prevent this?
>>>>In your WM_UPDATE_VIEWSETA handler, I suggest you verify that that all of the objects that are in your "viewset A" are still valid (and not in the process of being shut down).
I wrote my own version of UpdateAllViews and I iterate through all view and check if the handles are null, (it could be bad pointers instead of nulls too) but this does not solve the problem since the window could even be destroyed right after it passes the invalid handle check, and before it makes the actual update call. SO I would think checking for valid window object didnot solve the problem although I see enough evidence that the crash happens due to bad handle to the window object.
>>>>>BTW, a view update can take a looooong time (I'm thinking of one I wrote that involved database access). In that case your worker thread will be throwing lots of update requests into the event queue, and they will just pile up and your program might never catch up.
How would I prevent this?
Synchronizing the destroy and Update would not help either coz that would cause a deadlock.
It has been a hard problem to get around.
Any more ideas?
>>>The posted messages are probably piled up in the queue, and one of the OnUpdate() calls is being executed during a moment in which the CView-derived object still exists, but the window it encapsulates does not.
How would I prevent this?
>>>>In your WM_UPDATE_VIEWSETA handler, I suggest you verify that that all of the objects that are in your "viewset A" are still valid (and not in the process of being shut down).
I wrote my own version of UpdateAllViews and I iterate through all view and check if the handles are null, (it could be bad pointers instead of nulls too) but this does not solve the problem since the window could even be destroyed right after it passes the invalid handle check, and before it makes the actual update call. SO I would think checking for valid window object didnot solve the problem although I see enough evidence that the crash happens due to bad handle to the window object.
>>>>>BTW, a view update can take a looooong time (I'm thinking of one I wrote that involved database access). In that case your worker thread will be throwing lots of update requests into the event queue, and they will just pile up and your program might never catch up.
How would I prevent this?
Synchronizing the destroy and Update would not help either coz that would cause a deadlock.
It has been a hard problem to get around.
Any more ideas?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks a Lot Dan...
In your WM_UPDATE_VIEWSETA handler, I suggest you verify that that all of the objects that are in your "viewset A" are still valid (and not in the process of being shut down).
BTW, a view update can take a looooong time (I'm thinking of one I wrote that involved database access). In that case your worker thread will be thowing lots of update requests into the event queue, and they will just pile up and your program might never catch up.