1、线程函数声明
DWORD WINAPI ThreadProc( LPVOID lpParameter);2、创建线程函数
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); lpThreadAttributes:它被设为NULL,表示使用缺省值。 dwStackSize,线程堆栈大小,一般=0,在任何情况下, Windows根据需要动态延长堆栈的大小。 lpStartAddress,指向线程函数的指针, 形式:@函数名,函数名称没有限制, 但是必须以下列形式声明: DWORD WINAPI ThreadProc (LPVOID pParam) , 格式不正确将无法调用成功。 lpParameter:向线程函数传递的参数,是一个指向结构的指针, 不需传递参数时,为NULL。 dwCreationFlags :线程标志,可取值如下 CREATE_SUSPENDED: 创建一个挂起的线程 0 :创建后立即激活。 lpThreadId:保存新线程的id。 返回值: 函数成功,返回线程句柄;函数失败返回false。 3、创建事件对象 HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性 BOOL bManualReset, // 复位方式 BOOL bInitialState, // 初始状态 LPCTSTR lpName // 对象名称 ); lpEventAttributes: 如果lpEventAttributes是NULL,事件将获得一个默认的安全符。 bManualReset: 指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当事件被一个等待线程释放以后,系统将会自动将事件状态复原为无信号状态。 bInitialState: 指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。 lpName: 指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。
4、WaitForSingleObject函数
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
hHandle 对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
dwMilliseconds [in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle 标记的对象被触发,或者时间到了。如果dwMilliseconds 为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds 为INFINITE,对象被触发信号后,函数才会返回。
执行成功,返回值指示出引发函数返回的事件。它可能为以下值:
WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
返回值:
WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。
WAIT_OBJECT_0 0x00000000 :核心对象已被激活
WAIT_TIMEOUT 0x00000102:等待超时
WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码
在这里举个例子:
先创建一个全局Event对象g_event:
CEvent g_event;
在程序中可以通过调用CEvent::SetEvent设置事件为有信号状态。
下面是一个线程函数MyThreadPro()
UINT CFlushDlg::MyThreadProc( LPVOID pParam )
{
WaitForSingleObject(g_event,INFINITE);
For(;;)
{
………….
}
return 0;
}
在这个线程函数中只有设置g_event为有信号状态时才执行下面的for循环,因为g_event是全局变量,所以我们可以在别的线程中通过g_event. SetEvent控制这个线程。
还有一种用法就是我们可以通过WaitForSingleObject函数来间隔的执行一个线程函数的函数体
UINT CFlushDlg::MyThreadProc( LPVOID pParam )
{
while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0)
{
………………
}
return 0;
}
在这个线程函数中可以通过设置MT_INTERVAL来控制这个线程的函数体多久执行一次,当事件为无信号状态时函数体隔MT_INTERVAL执行一次,当设置事件为有信号状态时,线程就执行完毕了。
5实例分析
#include <windows.h>//头文件#include <iostream.h>
//线程函数声明DWORD WINAPI Fun1Proc( LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
//全局变量
int tickets=100;HANDLE g_hEvent;
void main(){ HANDLE hThread1; HANDLE hThread2;
//创建事件,NULL默认安全性;FALSE自动重置事件对象,当线程等到该事件的所有权后,系统自动将该对象设为无信号状态;TRUE初始有信号;NULL无名事件
g_hEvent=CreateEvent(NULL,FALSE,TRUE,NULL);
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);//创建线程 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); CloseHandle(hThread1);//关闭线程 CloseHandle(hThread2);
Sleep(4000);//延时4s
CloseHandle(g_hEvent);//关闭事件}
//线程函数实现
DWORD WINAPI Fun1Proc(LPVOID lpParameter){ while(TRUE) { WaitForSingleObject(g_hEvent,INFINITE);//等待事件
if(tickets>0) { Sleep(1); cout<<"thread1 sell ticket : "<<tickets--<<endl; SetEvent(g_hEvent);//设置事件有信号 } else { SetEvent(g_hEvent); break; } } return 0;}
DWORD WINAPI Fun2Proc(LPVOID lpParameter){ while(TRUE) { WaitForSingleObject(g_hEvent,INFINITE);
if(tickets>0) { Sleep(1); cout<<"thread2 sell ticket : "<<tickets--<<endl; SetEvent(g_hEvent); } else { SetEvent(g_hEvent); break; } } return 0;}