多线程绘图之:Multiple Threads and GDI Objects

我们有可能需要利用多线程来实现并行绘图。

但是,这里面经常会有这样一个问题:多个线程都需要使用同一个GDI对象进行绘制。

进而引申出来的问题是:多个不同的线程能否同时操作同一个GDI对象?

 

首先看MSDN里官方的document 描述(在MSDN里搜索“Multiple Threads and GDI Objects”):

 

To enhance performance, access to graphics device interface (GDI) objects (such as palettes, device contexts, regions, and the like) is not serialized. This creates a potential danger for processes that have multiple threads sharing these objects. For example, if one thread deletes a GDI object while another thread is using it, the results are unpredictable. This danger can be avoided simply by not sharing GDI objects. If sharing is unavoidable (or desirable), the application must provide its own mechanisms for synchronizing access. For more information about synchronizing access, see Synchronizing Execution of Multiple Threads.

 

可见,Windows为了GDI操作的效率,GDI API在设计的时候,没有被设计成线程安全的。

因此不要在多个线程里同时操作同一个GDI对象,如果你必须这么做,那得用同步机制来保证线程对这个GDI对象的依次访问操作。

 

举个例子:窗口上有2副图件(比如GIS领域里的等值线图,光照晕渲图),这2个图件的绘制过程比较复杂,在后台创建2个worker线程负责绘制。这里的问题是,2个worker线程都需要往同一个窗口上绘制,也就是往同一个DC(device context)上绘制。

DC也是Windows里的GDI对象之一。因此,不能让这2个线程同时调用GDI API对这个DC进行操作(比如:设置笔、文本等)。

 

对于这个例子中的解决方案: 利用内存DC。让后台work而线程先分配各自的内存DC,所有的绘制操作都在内存DC上进行,完成之后,通知主线程(可以使用PostThreadMessage,异步发送一个用户自定义的消息,[注:不要使用SendMessage函数。有关于消息发送,值得看一下这个文章http://www.flounder.com/messages.htm]),将内存DC上的内容拷贝到(BitBlt)主窗口的DC上。

注意:具体实现时,根据设计,最好利用“双缓冲”机制,针对每一副图件,创建2个内存DC,一前一后使用。也就是主窗口在显示的时候读取内存DC A进行显示;而后台线程在内存DC B上绘制,绘制完成后通知主线程。主线程得到通知后,对A和B进行交换(显示B,而A作为下一次后台线程操作的对象)。

 

VC Sample里有个例子叫MTGDI,这个例子使用了CRITICAL_SECTION来对“往同一个DC上的绘制操作”进行同步。

在实际应用中,这个方案的效率不好。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值