MFC中使用多线程主要有三种方式,分别如下:
1.CreateThread (windows)
HANDLE WINAPI CreateThread(
_in LPSECURITY_ATTRIBUTES lpThreadAttributes,
_in SIZE_T dwStackSize,
_in LPTHREAD_START_ROUTINE lpStartAddress,
_in LPVOID lpParameter,
_in DWORD dwCreationFlags,
_out LPDWORD lpThreadId
);
参数:
lpThreadAttributes: 指向一个LPSECURITY_ATTRIBUTES结构的指针决定返回的句柄能否被继承,如果lpThreadAttributes为空,这个句柄不能被继承。
sdStackSize:初始化的堆栈大小,以字节为单位。如果为0,使用默认的大小。
lpStartAddress:函数的入口地址,是一个函数指针。
lpParameter:一个指针,被传递到线程函数里。
dwCreationFlags:线程创建的标志。如果为CREATE_SUSPENDED这个标志,那么需要使用ResumeThread函数来激活线程函数,如果为NULL,线程函数立刻执行。
IpThreadId:一个指向线程id的指针,如果为空,线程id不被返回。
返回值:
1:如果函数成功执行,返回值将是这个新线程的句柄。如果失败,返回值是NULL。
2:当线程函数的起始地址无效(或者不可访问)时,CreateThread函数仍可能成功返回。如果该起始地址无效,则当线程运行时,异常将发生,线程终止,并返回一个错误代码,可以使用GetLastError获取。
说明:
1:如果线程函数return,返回值会隐式条用ExitThread函数,可以使用GetExitCodeThread函数获得该线程函数的返回值。
2:使用CreateThread创建的线程具有THREAD_PRIORITY_NORMAL线程优先级。可以使用GetThreadPriority和SetThreadPriority函数获取和设置线程优先级值。
3:当一个线程结束时,这个线程的对象将获得有信号状态,使得任何等待这个对象的线程都能够成功并继续执行下去。
4:系统中的线程对象一直存活到线程结束,并且所有指向它的句柄都需要通过调用CloseHandle关闭。
5:如果一个线程调用了CRT,应该使用_beginthreadex 和_endthreadex(需要使用多线程版的CRT)。
举例:
DWORD WINAPI ThreadMeasure(LPVOID lpParameter)
{
int a = (int)lpParameter;
CString str;
str.Format(_T("%d"),a);
AfxMessageBox(str);
return 0;
}
void CStationDlg::OnBnClickedstop()
{
// TODO: 在此添加控件通知处理程序代码
DWORD dwThreadId = 0; //线程id
HANDLE hThread=CreateThread(NULL, 0, ThreadMeasure, (LPVOID)919, 0, &dwThreadId); //返回线程句柄
//关闭句柄,线程结束后释放
CloseHandle(hThread);
}
2、AfxBeginThread
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
);
参数:
pfnThreadProc:线程函数的入口地址。
pThreadClass:继承CWinThread类的RUNTIME_CLASS对象。
pParam: 传递给线程函数的参数,可以为0。
nPriority:线程优先级。
nStackSize:指明线程堆栈的大小,以字节为单位,可以为0。
dwCreateFlags:线程创建标志。
lpSecurityAttrs:线程安全属性。
返回值:
如果成功则返回一个指针指向线程对象,否则为NULL。
说明:
可以调用AfxEndThread来终止线程或者return。
举例:
UINT _cdecl ThreadMeasure(LPVOID lpParameter)
{
int a = (int)lpParameter;
CString str;
str.Format(_T("%d"), a);
AfxMessageBox(str);
return 0;
}
void CStationDlg::OnBnClickedstop()
{
// TODO: 在此添加控件通知处理程序代码
CWinThread *pThread=AfxBeginThread(ThreadMeasure, (LPVOID)919);
}
3、_beginthread与_beginthreadex:
暂未使用,后补充
4、区别与联系
1、CreateThread是由操作系统提供的接口,
2、AfxBeginThread和_BeginThread则是编译器对它的封装。