现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

win32 API函数:事件

2013-07-27 23:53 工业·编程 ⁄ 共 2567字 ⁄ 字号 暂无评论

一、Event的有关函数

CreateEvent()  创建一个事件

OpenEvent()  打开一个已经创建的事件:使多个进程打开同一个事件对象的句柄,

从而达到进程之间同步的目的。

它只有在指定名称的事件对象已在其他地方被创建时才调用成功

SetEvent()  触发一个事件:将事件置为有信号状态

ResetEvent()  复位一个事件:将一个事件重置为无信号状态

PulseEvent()  触发并重置一个事件:使所有等待该事件的线程运行,当所有线程收到触发信号后,

事件将自动复位为无信号状态

WaitForSingleObject()  等待某个事件

WaitForMultipleObjects()  等待多个事件

二、关于手动事件和自动事件:

1、手动事件:

当事件对象处于活动状态时会一直处于这个状态,直到显式地将其置为无信号状态为止。

情况:对象处于有信号状态,用ResetEvent() 后所有等待线程都被唤醒。

2、自动事件:

当时间处于有信号状态并有一个线程接收到该事件后,事件立即变为无信号状态。

情况:事件在有一个等待线程被唤醒,且一直处于有信号状态。

三、事件和互斥量的异同

1、它们都可在进程间使用,有名时可用于进程之间的同步,无名时用于一个进程内的线程间同步。

2、对于事件:线程A等待某个时间发生,线程B在某个时间发生后产生一个信号,通知A

对于互斥量:主要是保证在任一时刻只有一个线程在使用资源,至于运行哪个线程则是随机的,由操作系统决定,所以它不能使两个线程按一定顺序执行。

3、关于有无信号的含义:

对于互斥量,当有线程使用互斥量时,其他线程不能获得此互斥量:此时互斥量为有信号

没有线程拥有该互斥量,线程可获得它并访问被它保护的资源:此时为无信号

对于事件,当等待的事件发生时,事件对象处于活动状态:此时事件为有信号

当等待的事件没发生时:此时事件为无信号

四、简单例子

HANDLE hEvent;

线程A:  WaitForSingleObject(hEvent,INGINITE);  //在事件上处于等待状态

线程B:  SetEvent(hEvent);  //用于触发一个事件

main:  hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//自动事件,无信号

handle1 = CreateThread(NULL,0,线程A,NULL,0,&dw1);

handle2 = CreateThread(NULL,0,线程B,NULL,0,&dw2);

CloseHandle(handle1);

CloseHandle(handle2);

CloseHandle(hEvent);

程序的运行结果是:A一直处于等待状态,直到B把事件触发为有信号状态时,A才能进入并执行动作。

五、关于共享缓冲区的例子

HANDLE hWriteEvent;

HANDLE hReadEvent[2];

CRITICAL_SECTION section; //声明一个临界段,因为读事件的输出屏幕共享,所以要进行同步操作

BOOL run=TRUE;

写线程:  hWriteEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//手动事件;无信号

while(run)

{

if(WaitForMultipleObject(2,hReadEvent,TRUE,0)==WAIT_OBJECT_0)//等待两个读事件都有信号

{

写入缓冲区;

PulseEvent(hWriteEvent); //使所有等待该事件的线程运行,当所有线程收到触发信号后,

事件将自动复位为无信号状态,即不等待

}

}

读线程1: hReadEvent[0] = CreateEvent(NULL,FALSE,TRUE,NULL);//自动事件;有信号

while(run)

{

WaitForSingleObject(hWriteEvent,INFINITE);  //等待写线程

EnterCriticalSection(&section);//进入临界区

把缓冲区的内容读出;

LeaveCriticalSection(&section);//离开临界区

SetEvent(hReadEvent[0]); //将事件置为有信号

}

读线程2:  hReadEvent[1] = CreateEvent(NULL,FALSE,TRUE,NULL);//自动事件;有信号

while(run)

{

WaitForSingleObject(hWriteEvent,INFINITE);  //等待写线程

EnterCriticalSection(&section);//进入临界区

把缓冲区的内容读出;

LeaveCriticalSection(&section);//离开临界区

SetEvent(hReadEvent[1]); //将事件置为有信号

}

控制线程: run=FALSE;//让运行停止

main:  InitializeCriticalSection(&section);

handle1=CreateThread(NULL,0,写线程,NULL,0,&dw1);

handle2=CreateThread(NULL,0,读线程1,NULL,0,&dw2);

handle3=CreateThread(NULL,0,读线程2,NULL,0,&dw3);

Sleep(1000);

handle4=CreateThread(NULL,0,控制线程,NULL,0,&dw4);//一秒钟后开启控制线程让进程停止

CloseHandle(handle1);

CloseHandle(handle2);

CloseHandle(handle3);

CloseHandle(handle4);

六、小结

1、以上都是对无名事件使用的举例,也就是在一个进程内的线程间。

2、事件在等待的时候,都是有信号的,在有信号的情况下,不断的试图得到事件的所有权

3、在 WaitForSingleObject 或 WaitForMultipleObject 得到执行之后,事件就变为无信号,即不在等待中。

4、要使用事件,必须先用等待函数去试图得到事件的所有权,得到事件所有权之后就可以进行操作;当操作完之后,要把事件置为有信号状态,把所有权交出。

5、从例2可以明显看出,事件可以同时为多个线程使用。

给我留言

留言无头像?