2013-07-04
在辅助线程的循环里检查一个全局变量很有意义,那么如果主线程这样做会怎么样呢?当然应该杜绝那么比较笨重的函数;
UINT ComputerThreadProc(LPVOID pParam)
{
g_nCount = 0;
while(g_nCount < 100){
//Do some computation here
::InterlockedIncrement((long*)&g_nCount);
}
return 0;
}
其实我们并不想让主线程进入一个循环,因为那样会浪费CPU周期,而且主线程总是有一个消息循环。这就是说,主线程有一个窗口(可见或不可见),而辅助线程有一个相应的窗口句柄。
辅助线程如何得到句柄呢?Win32线程函数参数就可以传递句柄。在调用AfxBeginThread时吧句柄传过去。为什么不传递C++窗口指针呢?那样有危险,因为我们不能依赖于对象的持续存在,我们也不允许在线程间共享MFC类的对象(此原则不适合直接从CObject派生的对象或者简单的类,如CRect和CString。)
我们是发送send消息还是寄出post消息呢?最好是寄出消息的方法。因为发送消息会引起主线程的MFC消息代码的重入,而这种模式的对话框就会出现问题。我们可以寄出什么样的消息呢?任何用户自定义的消息都可以。
有关线程阻塞的问题:
比如当我们调用Win32的Sleep函数,使线程睡眠。等很多函数阻塞线程,特别是访问硬件设备或internet主机的函数。如果在Win16方式下,这些函数会占用整个CPU直到他们完成为止;而在Win32下,他们允许其他的进程和线程继续执行。
在主用户界面里,我们要避免进行阻塞调用。记住,如果主线程阻塞,它就不能处理消息,这样会使程序显得很迟缓。如果我们有一个任务要求大量的文件IO,就应该吧相关的代码放在辅助线程里,然后在主线程里同步线程。
在辅助线程里,也要小心调用那些有可能被阻塞的函数。如果一个线程被永远阻塞了,那么只有当主线程退出时线程才会被终止,但是这样可能会有内存泄露。我们可以在主线程里调用Win32的函数TerminateThread,但仍然有内存泄露。
有关用户界面线程(UI线程)
MFC库提供了UI线程很好的支持,我们可以从CWinThread派生一个类,并使用AfxBeginThread的一个重要版本来启动线程。CWinTread的派生类有自己的InitInstance函数,最重要的有自己的消息循环。