I'm working on a multi-threaded win32 MFC application. We are rendering a map and displaying it in a pane in the user interface along with custom-rendered objects on top. It's slow to render (~800 ms), which is happening on the User Interface thread.
I'm trying to move the rendering onto its own thread so that the menus still remain snappy while the other rendering can still run in the background. The Draw thread will render continually using its own CDC. The UI thread will call a redraw function, which locks the mutex, and takes the last snapshot of the CBitmap
and draws it using the UI's CDC
. Every location where the Draw thread's CD
C is used, is locked by the mutex.
What I'm seeing is the thread creating a new CBitmap
via CreatCompatibleBitmap
, and then trying to select the new CBitmap
object into the Draw thread's CDC
.
this->m_canvas.CreateCompatibleDC(&compatibleDC);
this->m_bitmap = new CBitmap();
this->m_bitmap->CreateCompatibleBitmap(&compatibleDC, m_width, m_height);
m_oldBitmap = this->m_canvas.SelectObject(m_bitmap);
At this point, there is a debug ASSERT failure in CGdiObject::FromHandle().
CGdiObject* PASCAL CGdiObject::FromHandle(HGDIOBJ h)
{
CHandleMap* pMap = afxMapHGDIOBJ(TRUE); //create map if not exist
ASSERT(pMap != NULL);
CGdiObject* pObject = (CGdiObject*)pMap->FromHandle(h);
ASSERT(pObject == NULL || pObject->m_hObject == h);
return pObject;
}
The second ASSERT
is failing because the m_hObject
does not match the handle passed in. Basically, MFC is taking the handle, and doing a lookup to get a CBitmap
object which somehow doesn't match the CBitmap
that was just created.
Does this sound familiar to anyone? What could be happening to cause the FromHandle
method to return the wrong object? Is there a fundamental flaw with the way I create a CDC
for the Draw thread, and then re-use it over and over? Are there any approaches I can take to help debug/fix this problem?