2.事件对象
为了使用事件对象,在生成线程之前,第一步需要生成能够自动复位的事件内核对象hEvent,然后线程函数就通过WaitForSingleObject()函数等待hEvent的变为激发状态,WaitForSingleObject()函数只会在事件处于激发状态时才会返回,这样处于保护的代码就能运行。如果事件对象采用自动复位方式创建,当它处于激发状态后被WaitForSingleObject()等待到会马上变为未激发状态,比如在运行线程1中的被保护的代码时,事件对象已是未激发状态,这时候即便有其他线程来抢占CPU,也不会执行更不能访问被保护的共享资源,因为事件对象是未激发状态,WaitForSingleObject()不能够返回。在线程1()中的操作完成后能使用SetEvent()函数激发hEvent让其他线程取得对共享资源访问的权利。我们可以利用SetEvent()函数在某些指定操作完成后发出信号。
3.互斥对象
互斥对象(Mutex)是能够实现多种功能的一类内核对象。它可以保护共享资源,让多个线程对资源进行互斥操作。它在一些方面与关键代码段相同,要想获得操作资源的权利需要拥有互斥对象,因为只有一个互斥对象,所以在任何情况下被保护的共享资源不会同时受到来自多个线程的操作。拥有互斥对象的线程会在完成对共享资源的操作后释放互斥对象,这样别的线程就有机会取得互斥对象从而访问共享资源。
互斥对象,事件对象和关键代码段的比较
因为互斥对象和事件对象属于内核对象,所以采用内核对象实现线程同步时,速度会比较慢,但如果想实现在多个进程中的各个线程间的同步就需要采用内核对象。
关键代码段工作在用户方式下,虽然同步速度较快,但在使用关键代码段时,会比较容易进入死锁状态,这主要的原因是在等待进入关键代码段时无法设定超时值[7]。
考虑到本项目中只是用一个关键代码段对象,同时关键代码段在MFC中使用方便,通过关键代码段实习线程间同步。
2.3 图形刷新闪烁
MFC主要在OnDraw函数和OnPaint函数中完成画图过程,OnPaint函数调用OnDraw函数来显示屏幕。每次窗口发生重绘时,通常会先用背景色清除显示区,接着调用OnPaint函数,通常情况下背景色和画图的内容有很大的差别,这样背景色和显示的图像在较短时间内交替显示导致窗口像是在闪烁。为了让重画图像时不闪烁,最直接的方法是将背景刷设置为NULL。因为重画时没有了背景色清除以前绘画的内容,在以前的内容上直接绘画新的图形会导致窗口的显示很乱。为了避免闪烁同时又不会导致窗口显示很乱,第一步需要去掉MFC的背景刷新功能。我们可以将窗口的注册类中的背景刷成员赋值为NULL,窗口形成后我们也可以改变背景,通过传递给SetClassLong函数一个透明画刷实现。当然最简单的方式是重载OnEraseBkgnd函数,让其直接返回true。通过上述几种方式,我们去掉了背景刷新,窗口显示没有闪烁的情况,但同时如上所提,窗口显示很乱。为了解决闪烁的问题需要用到双缓存技术。所谓双缓存原理就是先在内存中创立一个虚拟的白纸,接着在这张白纸绘画一般比较复杂的内容,等到所有内容绘画结束后再将内存中的内容一次性从白纸上复制到窗口上显示。使用这样的方式能够使绘画的速度得以提高,同时绘画的效果也能极大的改进。
2.4 干净利落地结束多个线程
本设计需要实现由易到难多个层次,这就涉及到如何结束前一个层次的线程。结束线程大致有以下四种方式
2.4.1 线程函数返回
正常情况下,线程函数会在函数时自动结束线程。为了保证全部的线程相关资源能够得到清除彻底,应当让线程在函数返回时自动终止线程。假设线程采取这种方法并且顺利返回,那么:
- 上一篇:JSP图书馆座位管理系统设计+文献综述
- 下一篇:基于Android 平台的文件传输软件的设计与实现
-
-
-
-
-
-
-
中考体育项目与体育教学合理结合的研究
电站锅炉暖风器设计任务书
当代大学生慈善意识研究+文献综述
java+mysql车辆管理系统的设计+源代码
河岸冲刷和泥沙淤积的监测国内外研究现状
乳业同业并购式全产业链...
酸性水汽提装置总汽提塔设计+CAD图纸
大众媒体对公共政策制定的影响
杂拟谷盗体内共生菌沃尔...
十二层带中心支撑钢结构...