从儿童线程绘制到窗口

时间:2017-02-03 16:33:07

标签: multithreading winapi gdi

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

hdc = GetDC(hwnd);
SetDIBitsToDevice() ... or StretchDIBits()
ReleaseDC(hwnd, hdc);

在将我的应用程序移植到其他平台之后,我开始意识到从主线程以外的任何其他线程进行绘制通常是在许多平台(例如macOS)上禁止的。我的研究表明,Win32也许如此,但我仍然缺乏明确的答案。

因此,我的问题是:

是否允许从工作线程中如上所示绘制到我的窗口没有创建它正在绘制的窗口?请注意,工作线程实际上是绘制到窗口的唯一线程。主线程没有做任何绘图。甚至不在WM_PAINT。在我的情况下,绘制WM_PAINT是不必要的,因为工作线程以50fps的速度绘制。

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

1 个答案:

答案 0 :(得分:2)

  

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

它可能不是您问题的最佳解决方案,但只要您尊重GetDC的文档化规则,它就是安全的:

  
      
  • 请注意,DC的句柄一次只能由单个线程使用。
  •   必须从调用Int。的同一个线程调用
  • ReleaseDC   

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

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

<小时/> * 请参阅Thread affinity of user interface objects, part 2: Device contexts