线程创建有几个主要的函数,CreateThread和AfxBeginThread。
其中,在MFC环境下一般体检使用AfxBeginThread这个函数,原因是因为CreateThread这个函数使用并不安全。在MFC中使用AfxBrginThread偏多。
在使用AfxBeginThread的过程中,有几个参数比较重要,而且AfxBeginThread有两种使用格式,在MSDN中的格式如下:
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
如果使用的是第一个格式的函数的话,第一个参数和第二个参数很重要。其中第一个参数就是你的线程要启动的函数,就是线程的入口函数,这个函数有固定的格式,格式错误就不能够调用成功。而第二个函数这是该函数的参数。入口函数的格式如下:
UINT __cdeclMyControllingFunction( LPVOID pParam );
但是有一个问题,由于线程入口函数要求是全局函数,因此当我想要以线程方式启动我某个类的成员函数的时候,我该怎么做呢??
有两种方法,一种是将我的成员函数设置成静态函数,以供调用,但是静态函数是不能够调用类中的非静态成员函数,这就是吃力不讨好了。
第二种就是在外面创建一个全局函数,在全局函数中将入口函数的指针强制转换成类指针,然后通过指针调用成员函数,这个可以使用。
UINT CalSDInfo( LPVOID pParam )
{
CStoreViewDlg *pStoreView = (CStoreViewDlg*)pParam ;
pStoreView->GetSDUseInfo();
return 0;
}
通过这种格式的调用就能够调用类的成员函数了。
关于线程结束的方式也有两种,一种是我上面的使用方式,在入口函数执行完之后return 0,线程执行完入口函数之后,自然结束线程。但是这个方式也有缺点,比如说在入口函数还未执行完的时候,我离开了当前菜单,之后重新进入该菜单,这个时候程序又要重新创建一个线程再次计算这个结果,而且上个入口函数还没有执行完,这就会导致数据错误了!当然,如果通过一个循环来控制的话,就可以解决了,但是稍微要麻烦一点了,所以就采用下面的方法了!
为了辅助这种设计,因此,还需要强制停止线程。强制停止线程可以通过函数TerminateThread来完成。具体的调用格式如下:
DWORD threadActive;
GetExitCodeThread(m_thread->m_hThread,&threadActive);
if (STILL_ACTIVE ==threadActive)
{
TerminateThread(m_thread->m_hThread,0);
}
先对线程进行判断,判断线程是否还在运行,如果线程仍然运行的话,则强行终止线程。不过这个函数也有一定的缺陷,问题就是可能会造成死锁。这个问题先留住,下次就针对这几个线程结束的函数进行比对!