事件实现线程同步

    技术2022-05-19  21

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


    最新回复(0)