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。
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;
}