CreateThread函数的原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPWORD lpThreadID)
参数的含义:
lpThreadAttributes:
指向SECURITY_ATTRIBUTES的指针,用于定义新线程的安全属性,一般设置成NULL;
dwStackSize:
分配以字节数标书的线程堆栈的大小,默认值为0;
lpStartAddress:
指向一个线程函数地址,每个线程都有自己的线程函数,线程函数是线程的具体执行代码;
lpParameter:
传递给线程的参数;
dwCreationFlags:
表示创建线程的运行状态,其中CREATE_SUSPEND表示挂起当前线程,0表示立即指向单钱创建线程;
lpThreadID:
返回新创建的线程ID编号;
返回值:函数调用成功,返回新线程句柄,调用WaitForSingleObject函数等待所创建的线程结束;
WaitForSingleObject函数原型:
DWOED WaitForSingleObject(HANDLE hHandle,DWOED dwMilliseconds);
功能:
等待指定对象处于有信号状态或者等待时间结束的状态时,函数返回;
等待的对象可以为EVent、Job、Thread、Mutex、Process、Semaphore等;
当等待在挂起状态时,句柄被关闭,则该函数的行为是未定义的;
参数的含义:
hHandle:指定对象或时间的句柄;
dwMilliseconds:等待时间,以毫秒为单位,当潮所等待时间时,函数返回,如参数设置为0,则函数立即返回,如果设置为INFINITE,则函数直到有信号才返回。
临界区的使用步骤:
临界区对象是定义在数据段中的一个CRITICAL_SECTION结构,Windows内部使用这个结构记录一些信息确保同一时间只有一个线程访问修改数据段中的数据;
临界区使用:
a.初始化一个CRITICAL_SECTION结构;使用前,定义全局CRITICAL_SECTION变量,在调用创建线程函数前调用InitializeCriticalSection函数初始化临界区对象;
b.申请进入一个临界区:在线程中要对保护的数据进行操作前,调用EnterCriticalSection函数申请进入临区,同一时间内只能有一个线程进入临界区,所以在申请的时候已经有一个线程进入临界区,该线程则等待另一线程执行完临界区代码;
c.离开临界区:执行完临界区代码后们需要调用LeaveCriticalSection函数离开临界区;
d.删除临界区:当不需要临界区时调用DeleteCriticalSection函数将临界区对象删除;
多线程使用过程(CreateThread和CRITICAL_SECTION):
#include <stdio.h>
#include <windows.h>
HANDLE hfile;
CRITICAL_SECTION cs //临界区全局变量
DWORD WINAPI Thread(LPVOID lpParam)
{
...
EnterCriticalSection(&cs);
//操作公共资源
LeaveCriticalSection(&cs);
...
}
int main()
{
...
//初始化临界区资源
InitializeCriticalSection(&cs);
DWORD ThreadID;
//创建线程
HANDLE hHandle = CreateThread(NULL,0,Thread,NULL,0,&ThreadID);
WaitForSingleObjects(hHandle,500);
DeleteCriticalSection(&cs);
CloseHandle(hHandle);
}
AfxBeginThread是MFC对Windows的SDK接口CreateThread的封装,_beginthread是C的运行库函数,CreateThread是由操作系统提供的接口,而AfxBeginThread和_BeginThread则是编译器对它的封装。
AfxBeginThread函数和CreateThread函数的实质都是一样的,AfxBeginThread返回一个CWinThread的指针,它会new一个CWinThread对象,而且这个对象是自动删除的(在线程运行结束时),不便的是无法获得它的状态,因为随时都有可能这个指针指向的是一个已经无效的内存区域。CreatThread返回的是一个句柄,如果你不使用CloseHandle的话就可以通过他安全的了解线程状态,最后不要的时候CloseHandle,Windows才会释放资源。
如果用MFC编程,不要用CreateThread,如果只是使用Runtime Library,用_BegingThread。在MFC和RTL中的函数有可能会用到些它们所封装的公用变量,也就是说AfxBeginThread和_BeginThread都有自己的启动代码是CreateThread所没有的。在用CreateThread所创建的线程中使用MFC的类和RTL函数就有可能出现问题。如果你是用汇编编写win32程序并且在线程函数中也不调用MFC和RTL的函数,那用CreateThread就没问题,或者你虽然是用C写线程函数,但你很小心没调用RTL函数也不会有问题。
RTL提供的大部分与语言本身、编译器、操作系统及进程有关;它提供的函数通常很普遍,在其他开发工具中也能找到类似的函数;RTL类都直接继承自TObject或RTL内部的类。