多执行线程并不能让程序执行得比较快(除非是在多CPU 机器上,并且使用支持symmetric multiprocessing 的操作系统),只是能够让程序比较「有反应」。
从MFC的角度看,则把执行线程划分为和使用者接口无关的worker threads,以及和使用者接口(UI)有关的UI threads。
较好的作法是把所有UI(User Interface)动作都集中在主执行线程中,其它的「纯种运算工作」才考虑交给worker threads去做。
为程序产生第一个进程和执行线程,是系统加载器以及核心模块(KERNEL32)合作的结果。所以,再次循着第6章一步步剖析的步骤,MFC 程序的第一个动作是CWinApp::CWinApp(比WinMain 还早),在那里没有「产生执行线程」的动作,而是已经开始在收集执行线程的相关信息了。
虽然MFC 程序只会有一个CWinApp 对象,而CWinApp 衍生自CWinThread,但并不是说一个MFC 程序只能有一个CWinThread 对象。每当你需要一个额外的执行线程,不
应该在MFC 程序中直接调用::CreateThread 或_beginthreadex,应该先产生一个CWinThread 对象,再调用其成员函数CreateThread 或全域函数AfxBeginThread 将执行线程产生出来。,如果要产生一个UI thread,你还必须先定义一个CWinThread 衍生类别,再调用AfxBeginThread 产生一个CWinThread 对象。
执行线程的结束
既然worker thread 的生命就是执行线程函数本身,函数一旦return,执行线程也就结束了,自然得很。或者执行线程函数也可以调用AfxEndThread,结束一个执行线程。
UI 执行线程因为有消息循环的关系,必须在消息队列中放一个WM_QUIT,才能结束执行线程。放置的方式和一般Win32 程序一样,调用::PostQuitMessage 即可办到。亦或者,
在执行线程的任何一个函数中调用AfxEndThread,也可以结束执行线程。AfxEndThread 其实也是个外包装,其内部调用_endthreadex,这个动作才真正把执行线程结束掉。
别忘了,不论worker thread 或UI thread,都需要一个CWinThread 对象,当执行线程结束,记得把该对象释放掉(利用delete)。
Windows 系统提供四种同步化机制:
1. Critical Section(关键区域)
2. Semaphore(号志)
3. Event(事件)
4. Mutex(Mutual Exclusive,互斥器)