我正在开发一个多线程的win32 MFC应用程序。我们正在渲染一幅地图,并将其显示在用户界面的窗格中,并在顶部显示自定义渲染的对象。渲染速度很慢(大约800ms),这是在用户界面线程上发生的。
我正在尝试将渲染移动到它自己的线程上,以便菜单仍然保持快速,而其他渲染仍然可以在后台运行。绘图线程将使用它自己的CDC连续渲染。UI线程将调用一个重画函数,该函数锁定互斥锁,并获取CBitmap
的最后一个快照,并使用UI的CDC
绘制它。使用绘制线程的CD
C的每个位置都被互斥锁。
我看到的是线程通过CreatCompatibleBitmap
创建一个新的CBitmap
,然后尝试将新的CBitmap
对象选择到绘图线程的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()中出现调试断言失败。
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
不匹配的CBitmap
对象。
这对任何人来说都很熟悉吗?可能发生了什么导致FromHandle
方法返回错误的对象?我为绘图线程创建CDC
,然后一遍又一遍地重用它的方式有没有根本的缺陷?有什么方法可以帮助调试/解决这个问题吗?
发布于 2009-10-16 17:23:31
金色的。句柄和对象之间的映射在thread-local storage中。
在多线程环境中,由于窗口归线程所有,
将临时和永久窗口句柄映射保存在线程本地存储区中。其他句柄映射也是如此,比如GDI对象和设备上下文。将窗口句柄映射保存在线程本地存储中可确保防止多个线程同时访问。
所以基本上,存储句柄,然后从句柄创建一个CBitmap,以便在线程之间操作它们。
我的错误在于UI线程创建了我的CBitmap,然后从两个线程访问CBitmap对象。
https://stackoverflow.com/questions/1579154
复制