从子线程绘制到窗口

And*_*eas 3 winapi multithreading gdi

我的应用程序从工作线程绘制图形已有 10 多年了,而且我从未遇到过任何问题。工作线程绘制到 my HWND(由主线程创建),如下所示:

hdc = GetDC(hwnd);
SetDIBitsToDevice() ... or StretchDIBits()
ReleaseDC(hwnd, hdc);
Run Code Online (Sandbox Code Playgroud)

将我的应用程序移植到其他平台后,我开始意识到,在许多平台(例如 macOS)上,从主线程以外的任何其他线程进行绘图通常是不行的。我的研究表明,对于 Win32 来说这也可能是正确的,但我仍然缺乏明确的答案。

因此,我的问题是:

是否允许从未创建它正在绘制的窗口的工作线程绘制到我的窗口,如上所示?请注意,工作线程实际上是唯一绘制窗口的线程。主线程不做任何绘图。即使在WM_PAINT. 在我的例子中,绘制WM_PAINT是不必要的,因为工作线程以 50fps 绘制。

如果不允许,将绘图从工作线程委托给主线程的最佳方法是什么?

IIn*_*ble 5

是否允许从未创建它正在绘制的窗口的工作线程绘制到我的窗口,如上所示?

它可能不是解决您问题的最佳解决方案,但只要您遵守以下记录的规则,它就是安全的GetDC

  • 请注意,DC 的句柄在任何时候只能由单个线程使用。
  • ReleaseDC必须从调用 的同一线程中调用GetDC

如果您确实从多个线程渲染到同一设备上下文,则您负责同步对其的访问。*

正如评论中所解释的,更好的解决方案是从工作线程生成 DIB,并让该线程通过调用来更新窗口RedrawWindow。然后主线程可以StretchBlt在其WM_PAINT处理程序中。跨线程调用RedrawWindow实现了同步屏障。当调用返回时,目标线程上的渲染已完成,并且可以安全地重新使用 DIB。


* 请参阅用户界面对象的线程关联,第 2 部分:设备上下文