从子线程绘图到窗口 [英] Drawing to window from child thread

查看:66
本文介绍了从子线程绘图到窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序已经从工作线程绘制图形了10多年了,我从没有遇到任何问题.工作者线程像这样绘制到我的HWND(由主线程创建):

My app has been drawing its graphics from a worker thread for over 10 years now and I've never had any problems with it. The worker thread draws to my HWND (created by the main thread) like this:

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

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

After having ported my app to other platforms, I began to realize that drawing from any other thread than the main thread is usually a no-go on many platforms (e.g. macOS). My research has shown that this might be true for Win32 as well but I'm still lacking a definite answer.

因此,我的问题:

是否允许从没有创建要绘制到的窗口的工作线程向我的窗口绘制如上所示的窗口?请注意,工作线程实际上是唯一绘制到窗口的线程.主线程不做任何绘图.甚至在WM_PAINT中也没有.在我的情况下,不需要使用WM_PAINT进行绘制,因为辅助线程的绘制速度为50fps.

Is it allowed to draw to my window like shown above from a worker thread that did not create the window it is drawing to? Note that the worker thread is really the only thread that draws to the window. The main thread doesn't do any drawing. Not even in WM_PAINT. Drawing in WM_PAINT is unnecessary in my case because the worker thread draws at 50fps.

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

If it isn't allowed, what's the best way to delegate drawing from the worker thread to the main thread?

推荐答案

是否可以从没有创建要绘制到的窗口的辅助线程中像上面显示的那样绘制到我的窗口?

Is it allowed to draw to my window like shown above from a worker thread that did not create the window it is drawing to?

这可能不是解决问题的最佳方法,但是只要您遵守

It may not be the best solution to your problem, but it's safe, as long as you respect the documented rules for GetDC:

  • 请注意,DC的句柄只能在任何时间由单个线程使用.
  • ReleaseDC必须从与调用GetDC相同的线程中调用.
  • Note that the handle to the DC can only be used by a single thread at any one time.
  • ReleaseDC must be called from the same thread that called GetDC.

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

If you do render to the same device context from multiple threads, you are responsible for synchronizing accesses to it.*

如评论中所述,更好的解决方案是从工作线程生成DIB,并让该线程通过调用

As explained in the comments, a better solution would be to generate the DIB from the worker thread, and have this thread update the window by calling RedrawWindow. The main thread can then StretchBlt in its WM_PAINT handler. Calling RedrawWindow across threads implements a synchronization barrier. When the call returns, rendering on the target thread has run to completion, and it's safe to re-use the DIB.


* 请参见
线程的亲和力用户界面对象,第2部分:设备上下文 .


* See Thread affinity of user interface objects, part 2: Device contexts.

这篇关于从子线程绘图到窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆