ASSERT 在 CDC SelectObject() 调用上失败 - 我可以尝试什么?

发布于 2024-08-07 19:33:20 字数 1336 浏览 3 评论 0原文

我正在开发一个多线程 win32 MFC 应用程序。我们正在渲染地图并将其显示在用户界面的窗格中,并在顶部显示自定义渲染的对象。渲染速度很慢(约 800 毫秒),这是在用户界面线程上发生的。

我试图将渲染移动到它自己的线程上,以便菜单仍然保持活泼,而其他渲染仍然可以在后台运行。 Draw 线程将使用其自己的 CDC 持续渲染。 UI 线程将调用重绘函数,该函数会锁定互斥体,并获取 CBitmap 的最后一个快照,并使用 UI 的 CDC 绘制它。使用 Draw 线程的 CD 的每个位置都被互斥体锁定。

我看到的是线程通过 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() 中出现调试 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< /code> 对象在某种程度上与刚刚创建的 CBitmap 不匹配。

这听起来很熟悉吗?可能发生什么情况导致 FromHandle 方法返回错误的对象?我为 Draw 线程创建 CDC,然后一遍又一遍地重复使用它的方式是否存在根本缺陷?我可以采取任何方法来帮助调试/解决这个问题吗?

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 CDC 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜无邪 2024-08-14 19:33:20

金的。句柄和对象之间的映射位于线程本地存储中。

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

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

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

Golden. The mapping between handles and objects are in thread-local storage.

In a multi-threaded environment
because windows are owned by threads,
MFC keeps the temporary and permanent
window handle map in thread local
storage. The same is true for other
handle maps like those for GDI objects
and device contexts. Keeping the
window handle maps in thread local
storage ensures protection against
simultaneous access by several
threads.

So basically, store the handle, then create a CBitmap from the handle in order to manipulate them between threads.

My mistake was in the UI thread creating my CBitmap, and then accessing the CBitmap object from both threads.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文