【发布时间】:2010-12-07 10:34:53
【问题描述】:
我正在开发一个多线程的 win32 MFC 应用程序。我们正在渲染地图并将其与顶部的自定义渲染对象一起显示在用户界面的窗格中。渲染速度很慢(约 800 毫秒),这发生在用户界面线程上。
我正在尝试将渲染移到它自己的线程上,以便菜单仍然保持快速,而其他渲染仍然可以在后台运行。 Draw 线程将使用它自己的 CDC 持续渲染。 UI 线程将调用重绘函数,该函数锁定互斥体,并获取CBitmap 的最后一个快照并使用 UI 的CDC 绘制它。每个使用 Draw 线程的CDC 的位置都被互斥锁锁定。
我看到的是线程通过CreatCompatibleBitmap 创建一个新的CBitmap,然后尝试将新的CBitmap 对象选择到Draw 线程的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);
此时,CGdiObject::FromHandle()中出现debug ASSERT失败。
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;
}
第二个ASSERT 失败,因为m_hObject 与传入的句柄不匹配。基本上,MFC 正在获取句柄,并进行查找以获取与@ 不匹配的CBitmap 对象刚刚创建的 987654333@。
这听起来对任何人来说都很熟悉吗?会发生什么导致FromHandle 方法返回错误的对象?我为 Draw 线程创建 CDC 然后一遍又一遍地重复使用它的方式是否存在根本缺陷?有什么方法可以帮助调试/解决这个问题?
【问题讨论】:
-
这很奇怪:当您在 CGdiObject::FromHandle() 中时,我们正在处理来自 ::SelectObject() 的返回值,并且不明显这会如何出错。断言发生时 pObject 看起来像一个有效对象吗?
-
是的。 pObject 是有效的,并且是一个 CBitmap……但与在“new Bitmap()”语句中构造的 CBitmap 不同。
-
每个线程都有一个句柄->对象查找映射...我在一个线程中创建 CBitmap,然后尝试在另一个线程中使用它...映射中的查找失败。