【问题标题】:ASSERT fails on CDC SelectObject() call - What can I try?ASSERT 在 CDC SelectObject() 调用上失败 - 我可以尝试什么?
【发布时间】: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,然后尝试在另一个线程中使用它...映射中的查找失败。

标签: c++ mfc assert


【解决方案1】:

金色。句柄和对象的映射在thread-local storage

在多线程环境中 因为窗口归线程所有, MFC 保持临时和永久 线程本地的窗口句柄映射 贮存。其他的也一样 处理 GDI 对象的映射 和设备上下文。保持 线程本地的窗口句柄映射 存储确保防止 多人同时访问 线程。

所以基本上,存储句柄,然后从句柄创建一个 CBitmap 以便在线程之间操作它们。

我的错误在于 UI 线程创建了我的 CBitmap,然后从两个线程访问 CBitmap 对象。

【讨论】:

  • 嘿。出于完全相同的原因,将绘制代码移动到自己的线程中犯了完全相同的错误。得到了一些很好的答案和参考,提出了可能有价值的类似问题; stackoverflow.com/questions/2287114/…
  • 你能举例说明你是如何存储Handle的吗?
  • 是 MFC 将句柄存储为 CBitmap 实现的一部分。如果您正在寻找有关 Handles 或线程本地存储的特定内容,请提出一个新问题以获得更多人的帮助!
猜你喜欢
  • 1970-01-01
  • 2016-04-01
  • 2023-03-23
  • 1970-01-01
  • 2015-08-20
  • 2012-12-10
  • 1970-01-01
  • 2022-01-23
  • 2012-12-17
相关资源
最近更新 更多