gpt4 book ai didi

c++ - 从辅助线程调用 UpdateWindow()

转载 作者:可可西里 更新时间:2023-11-01 10:15:03 26 4
gpt4 key购买 nike

我有一个用于显示非常复杂的 vector 图形的 Windows 应用程序。由于绘图需要一段时间才能完成,我将渲染逻辑移到了一个单独的线程中。

相关代码片段如下。这里的CCanvas是从CWnd派生出来的,m_MemDC是绘制所有图形的CDC指针。 OnPaint() 处理程序将此 memdc 内容位传输到 PaintDC。

在 Render() 方法中,一旦图像绘制完成,我必须更新显示窗口。这里我直接调用了 Invalidate()UpdateWindow() 方法。从辅助线程调用这些方法是否安全?

void CCanvas::UpdateDisplay()
{
::SetEvent(m_hRenderWaitEvent);
}

DWORD WINAPI RenderThread(LPVOID lpParam)
{
CCanvas* pThis = static_cast<CCanvas*>(lpParam);
pThis->Render();

return 0;
}

void CCanvas::Render()
{
HANDLE hEvents[] = {m_hStopEvent, m_hRenderWaitEvent};
while (true)
{
switch (WaitForMultipleObjects(2, hEvents, FALSE, INFINITE))
{
case WAIT_OBJECT_0 + 0:
return;
case WAIT_OBJECT_0 + 1:
Draw(&m_MemDC);
Invalidate();
UpdateWindow();
break;
}
}
}

void CCanvas::Draw( CDC* pDC )
{
//Image drawing logic here
}

void CCanvas::OnPaint()
{
CPaintDC dc( this );

CRect rctClient;
GetClientRect( rctClient );
dc.BitBlt( rctClient.left, rctClient.top, rctClient.Width(), rctClient.Height(), &m_MemDC, rctClient.left, rctClient.top, SRCCOPY );
}

最佳答案

不,在创建窗口的线程以外的线程上调用 GUI 函数是不安全的。

我会创建一条自定义消息,以便在图像准备好后从后台线程发布。然后主线程可以在正常的消息循环中处理这个以重绘窗口。

注意:您需要确保用于后台渲染的机制正确同步:例如在对 m_MemDC 的访问周围使用互斥锁,以避免后台线程在前台线程读取它以绘制 UI 时尝试更新它。

我实际上建议使用两个 绘画缓冲区。一个用作渲染目标,一个由 WM_PAINT 处理程序读取。渲染完成后,渲染线程可以锁定互斥锁、交换缓冲区、解锁互斥锁并发布消息。 WM_PAINT 处理程序可以锁定互斥锁、从事件缓冲区复制到窗口以及解锁互斥锁。这意味着渲染线程只会在交换“事件缓冲区”标记所需的时间内阻塞消息处理线程,而不是如果 WM_PAINT 因任何其他原因被调用时的整个渲染时间(例如,您的窗口被遮盖/未遮盖,或调整大小,或其他)

关于c++ - 从辅助线程调用 UpdateWindow(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42896439/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com